diff options
author | bms <bms@FreeBSD.org> | 2003-08-20 14:46:40 +0000 |
---|---|---|
committer | bms <bms@FreeBSD.org> | 2003-08-20 14:46:40 +0000 |
commit | 3af3c5ae44ef98b9f2da135dcb64cfc12acd0f39 (patch) | |
tree | b0740a95462efb0df015bc34d5d05f5d96cd2f3b | |
parent | 5546ba50272e71097a2f7c6b9fbec902cf58c4ea (diff) | |
download | FreeBSD-src-3af3c5ae44ef98b9f2da135dcb64cfc12acd0f39.zip FreeBSD-src-3af3c5ae44ef98b9f2da135dcb64cfc12acd0f39.tar.gz |
Add the IP_ONESBCAST option, to enable undirected IP broadcasts to be sent on
specific interfaces. This is required by aodvd, and may in future help us
in getting rid of the requirement for BPF from our import of isc-dhcp.
Suggested by: fenestro
Obtained from: BSD/OS
Reviewed by: mini, sam
Approved by: jake (mentor)
-rw-r--r-- | share/man/man4/ip.4 | 41 | ||||
-rw-r--r-- | sys/netinet/in.h | 2 | ||||
-rw-r--r-- | sys/netinet/in_pcb.h | 1 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 12 | ||||
-rw-r--r-- | sys/netinet/ip_var.h | 1 | ||||
-rw-r--r-- | sys/netinet/raw_ip.c | 3 | ||||
-rw-r--r-- | sys/netinet/udp_usrreq.c | 8 |
7 files changed, 66 insertions, 2 deletions
diff --git a/share/man/man4/ip.4 b/share/man/man4/ip.4 index d7453da..0203039 100644 --- a/share/man/man4/ip.4 +++ b/share/man/man4/ip.4 @@ -175,6 +175,47 @@ can be used directly as a control message for .Xr sendmsg 2 . .Pp If the +.Dv IP_ONESBCAST +option is enabled on a +.Dv SOCK_DGRAM +or a +.Dv SOCK_RAW +socket, the destination address of outgoing +broadcast datagrams on that socket will be forced +to the undirected broadcast address, +.Dv INADDR_BROADCAST , +before transmission. +This is in contrast to the default behavior of the +system, which is to transmit undirected broadcasts +via the first network interface with the +.Dv IFF_BROADCAST flag set. +.Pp +This option allows applications to choose which +interface is used to transmit an undirected broadcast +datagram. +For example, the following code would force an +undirected broadcast to be transmitted via the interface +configured with the broadcast address 192.168.2.255: +.Bd -literal +char msg[512]; +struct sockaddr_in sin; +u_char onesbcast = 1; /* 0 = disable (default), 1 = enable */ + +setsockopt(s, IPPROTO_IP, IP_ONESBCAST, &onesbcast, sizeof(onesbcast)); +sin.sin_addr.s_addr = inet_addr("192.168.2.255"); +sin.sin_port = htons(1234); +sendto(s, msg, sizeof(msg), 0, &sin, sizeof(sin)); +.Ed +.Pp +It is the application's responsibility to set the +.Dv IP_TTL option +to an appropriate value in order to prevent broadcast storms. +The application must have sufficient credentials to set the +.Dv SO_BROADCAST +socket level option, otherwise the +.Dv IP_ONESBCAST option has no effect. +.Pp +If the .Dv IP_RECVTTL option is enabled on a .Dv SOCK_DGRAM diff --git a/sys/netinet/in.h b/sys/netinet/in.h index 63bd1ce..8aafb24 100644 --- a/sys/netinet/in.h +++ b/sys/netinet/in.h @@ -388,6 +388,8 @@ __END_DECLS #define IP_IPSEC_POLICY 21 /* int; set/get security policy */ #define IP_FAITH 22 /* bool; accept FAITH'ed connections */ +#define IP_ONESBCAST 23 /* bool: send all-ones broadcast */ + #define IP_FW_ADD 50 /* add a firewall rule to chain */ #define IP_FW_DEL 51 /* delete a firewall rule from chain */ #define IP_FW_FLUSH 52 /* flush firewall rule chain */ diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h index 9893af6..96521e4 100644 --- a/sys/netinet/in_pcb.h +++ b/sys/netinet/in_pcb.h @@ -142,6 +142,7 @@ struct inpcb { #define INP_IPV6 0x2 #define INP_IPV6PROTO 0x4 /* opened under IPv6 protocol */ #define INP_TIMEWAIT 0x8 /* .. probably doesn't go here */ +#define INP_ONESBCAST 0x10 /* send all-ones broadcast */ u_char inp_ip_ttl; /* time to live proto */ u_char inp_ip_p; /* protocol proto */ diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 60d5b1d..4a507cf 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -477,6 +477,8 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro, error = EMSGSIZE; goto bad; } + if (flags & IP_SENDONES) + ip->ip_dst.s_addr = INADDR_BROADCAST; m->m_flags |= M_BCAST; } else { m->m_flags &= ~M_BCAST; @@ -1473,6 +1475,7 @@ ip_ctloutput(so, sopt) case IP_RECVTTL: case IP_RECVIF: case IP_FAITH: + case IP_ONESBCAST: error = sooptcopyin(sopt, &optval, sizeof optval, sizeof optval); if (error) @@ -1515,6 +1518,10 @@ ip_ctloutput(so, sopt) case IP_FAITH: OPTSET(INP_FAITH); break; + + case IP_ONESBCAST: + OPTSET(INP_ONESBCAST); + break; } break; #undef OPTSET @@ -1608,6 +1615,7 @@ ip_ctloutput(so, sopt) case IP_RECVIF: case IP_PORTRANGE: case IP_FAITH: + case IP_ONESBCAST: switch (sopt->sopt_name) { case IP_TOS: @@ -1652,6 +1660,10 @@ ip_ctloutput(so, sopt) case IP_FAITH: optval = OPTBIT(INP_FAITH); break; + + case IP_ONESBCAST: + optval = OPTBIT(INP_ONESBCAST); + break; } error = sooptcopyout(sopt, &optval, sizeof optval); break; diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index 5a9a1ca..d0fde8e 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -139,6 +139,7 @@ struct ipstat { /* flags passed to ip_output as last parameter */ #define IP_FORWARDING 0x1 /* most of ip header exists */ #define IP_RAWOUTPUT 0x2 /* raw ip header exists */ +#define IP_SENDONES 0x4 /* send all-ones broadcast */ #define IP_ROUTETOIF SO_DONTROUTE /* bypass routing tables */ #define IP_ALLOWBROADCAST SO_BROADCAST /* can send broadcast packets */ diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 05447b4..d4766ab 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -322,6 +322,9 @@ rip_output(m, so, dst) ipstat.ips_rawout++; } + if (inp->inp_flags & INP_ONESBCAST) + flags |= IP_SENDONES; + return (ip_output(m, inp->inp_options, &inp->inp_route, flags, inp->inp_moptions, inp)); } diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 794461e..6b8b87e 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -693,6 +693,7 @@ udp_output(inp, m, addr, control, td) struct cmsghdr *cm; struct sockaddr_in *sin, src; int error = 0; + int ipflags; u_short fport, lport; #ifdef MAC @@ -821,6 +822,10 @@ udp_output(inp, m, addr, control, td) ui->ui_dport = fport; ui->ui_ulen = htons((u_short)len + sizeof(struct udphdr)); + ipflags = inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST); + if (inp->inp_flags & INP_ONESBCAST) + ipflags |= IP_SENDONES; + /* * Set up checksum and output datagram. */ @@ -837,8 +842,7 @@ udp_output(inp, m, addr, control, td) ((struct ip *)ui)->ip_tos = inp->inp_ip_tos; /* XXX */ udpstat.udps_opackets++; - error = ip_output(m, inp->inp_options, &inp->inp_route, - (inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST)), + error = ip_output(m, inp->inp_options, &inp->inp_route, ipflags, inp->inp_moptions, inp); return (error); |