]>
git.ipfire.org Git - thirdparty/bird.git/blob - sysdep/bsd/sysio.h
2 * BIRD Internet Routing Daemon -- NetBSD Multicasting and Network Includes
4 * (c) 2004 Ondrej Filip <feela@network.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
22 #define TCP_MD5SIG TCP_SIGNATURE_ENABLE
28 set_inaddr(struct in6_addr
* ia
, ip_addr a
)
31 memcpy(ia
, &a
, sizeof(a
));
35 get_inaddr(ip_addr
*a
, struct in6_addr
*ia
)
37 memcpy(a
, ia
, sizeof(*a
));
45 #include <net/if_dl.h>
46 #include <netinet/in_systm.h> // Workaround for some BSDs
47 #include <netinet/ip.h>
50 set_inaddr(struct in_addr
* ia
, ip_addr a
)
53 memcpy(&ia
->s_addr
, &a
, sizeof(a
));
57 get_inaddr(ip_addr
*a
, struct in_addr
*ia
)
59 memcpy(a
, &ia
->s_addr
, sizeof(*a
));
64 /* BSD Multicast handling for IPv4 */
67 sysio_setup_multicast(sock
*s
)
73 if (setsockopt(s
->fd
, IPPROTO_IP
, IP_MULTICAST_LOOP
, &zero
, sizeof(zero
)) < 0)
74 return "IP_MULTICAST_LOOP";
76 if (setsockopt(s
->fd
, IPPROTO_IP
, IP_MULTICAST_TTL
, &ttl
, sizeof(ttl
)) < 0)
77 return "IP_MULTICAST_TTL";
79 /* This defines where should we send _outgoing_ multicasts */
80 set_inaddr(&m
, s
->iface
->addr
->ip
);
81 if (setsockopt(s
->fd
, IPPROTO_IP
, IP_MULTICAST_IF
, &m
, sizeof(m
)) < 0)
82 return "IP_MULTICAST_IF";
89 sysio_join_group(sock
*s
, ip_addr maddr
)
93 bzero(&mreq
, sizeof(mreq
));
94 set_inaddr(&mreq
.imr_interface
, s
->iface
->addr
->ip
);
95 set_inaddr(&mreq
.imr_multiaddr
, maddr
);
97 /* And this one sets interface for _receiving_ multicasts from */
98 if (setsockopt(s
->fd
, IPPROTO_IP
, IP_ADD_MEMBERSHIP
, &mreq
, sizeof(mreq
)) < 0)
99 return "IP_ADD_MEMBERSHIP";
105 sysio_leave_group(sock
*s
, ip_addr maddr
)
109 bzero(&mreq
, sizeof(mreq
));
110 set_inaddr(&mreq
.imr_interface
, s
->iface
->addr
->ip
);
111 set_inaddr(&mreq
.imr_multiaddr
, maddr
);
113 /* And this one sets interface for _receiving_ multicasts from */
114 if (setsockopt(s
->fd
, IPPROTO_IP
, IP_DROP_MEMBERSHIP
, &mreq
, sizeof(mreq
)) < 0)
115 return "IP_DROP_MEMBERSHIP";
121 /* BSD RX/TX packet info handling for IPv4 */
122 /* it uses IP_RECVDSTADDR / IP_RECVIF socket options instead of IP_PKTINFO */
124 #define CMSG_RX_SPACE (CMSG_SPACE(sizeof(struct in_addr)) + \
125 CMSG_SPACE(sizeof(struct sockaddr_dl)) + \
126 CMSG_SPACE(sizeof(char)))
127 #define CMSG_TX_SPACE CMSG_SPACE(sizeof(struct in_addr))
130 sysio_register_cmsgs(sock
*s
)
133 if (s
->flags
& SKF_LADDR_RX
)
135 if (setsockopt(s
->fd
, IPPROTO_IP
, IP_RECVDSTADDR
, &ok
, sizeof(ok
)) < 0)
136 return "IP_RECVDSTADDR";
138 if (setsockopt(s
->fd
, IPPROTO_IP
, IP_RECVIF
, &ok
, sizeof(ok
)) < 0)
142 if ((s
->flags
& SKF_TTL_RX
) &&
143 (setsockopt(s
->fd
, IPPROTO_IP
, IP_RECVTTL
, &ok
, sizeof(ok
)) < 0))
151 sysio_process_rx_cmsgs(sock
*s
, struct msghdr
*msg
)
154 struct in_addr
*ra
= NULL
;
155 struct sockaddr_dl
*ri
= NULL
;
156 unsigned char *ttl
= NULL
;
158 for (cm
= CMSG_FIRSTHDR(msg
); cm
!= NULL
; cm
= CMSG_NXTHDR(msg
, cm
))
160 if (cm
->cmsg_level
== IPPROTO_IP
&& cm
->cmsg_type
== IP_RECVDSTADDR
)
161 ra
= (struct in_addr
*) CMSG_DATA(cm
);
163 if (cm
->cmsg_level
== IPPROTO_IP
&& cm
->cmsg_type
== IP_RECVIF
)
164 ri
= (struct sockaddr_dl
*) CMSG_DATA(cm
);
166 if (cm
->cmsg_level
== IPPROTO_IP
&& cm
->cmsg_type
== IP_RECVTTL
)
167 ttl
= (unsigned char *) CMSG_DATA(cm
);
170 if (s
->flags
& SKF_LADDR_RX
)
176 get_inaddr(&s
->laddr
, ra
);
178 s
->lifindex
= ri
->sdl_index
;
181 if (s
->flags
& SKF_TTL_RX
)
182 s
->ttl
= ttl
? *ttl
: -1;
184 // log(L_WARN "RX %I %d", s->laddr, s->lifindex);
187 /* Unfortunately, IP_SENDSRCADDR does not work for raw IP sockets on BSD kernels */
190 sysio_prepare_tx_cmsgs(sock
*s
, struct msghdr
*msg
, void *cbuf
, size_t cbuflen
)
192 #ifdef IP_SENDSRCADDR
196 msg
->msg_control
= cbuf
;
197 msg
->msg_controllen
= cbuflen
;
199 cm
= CMSG_FIRSTHDR(msg
);
200 cm
->cmsg_level
= IPPROTO_IP
;
201 cm
->cmsg_type
= IP_SENDSRCADDR
;
202 cm
->cmsg_len
= CMSG_LEN(sizeof(*sa
));
204 sa
= (struct in_addr
*) CMSG_DATA(cm
);
205 set_inaddr(sa
, s
->saddr
);
207 msg
->msg_controllen
= cm
->cmsg_len
;
213 fill_ip_header(sock
*s
, void *hdr
, int dlen
)
221 ip
->ip_tos
= (s
->tos
< 0) ? 0 : s
->tos
;
222 ip
->ip_len
= 20 + dlen
;
223 ip
->ip_ttl
= (s
->ttl
< 0) ? 64 : s
->ttl
;
225 set_inaddr(&ip
->ip_src
, s
->saddr
);
226 set_inaddr(&ip
->ip_dst
, s
->daddr
);
229 /* OpenBSD expects ip_len in network order, other BSDs expect host order */
230 ip
->ip_len
= htons(ip
->ip_len
);
237 #include <netinet/tcp.h>
238 #ifndef TCP_KEYLEN_MAX
239 #define TCP_KEYLEN_MAX 80
242 #define TCP_SIG_SPI 0x1000
246 * FIXME: Passwords has to be set by setkey(8) command. This is the same
247 * behaviour like Quagga. We need to add code for SA/SP entries
252 sk_set_md5_auth_int(sock
*s
, sockaddr
*sa
, char *passwd
)
257 int len
= strlen(passwd
);
259 enable
= len
? TCP_SIG_SPI
: 0;
261 if (len
> TCP_KEYLEN_MAX
)
263 log(L_ERR
"MD5 password too long");
268 int rv
= setsockopt(s
->fd
, IPPROTO_TCP
, TCP_MD5SIG
, &enable
, sizeof(enable
));
272 if (errno
== ENOPROTOOPT
)
273 log(L_ERR
"Kernel does not support TCP MD5 signatures");
275 log(L_ERR
"sk_set_md5_auth_int: setsockopt: %m");
285 sk_set_min_ttl4(sock
*s
, int ttl
)
287 if (setsockopt(s
->fd
, IPPROTO_IP
, IP_MINTTL
, &ttl
, sizeof(ttl
)) < 0)
289 if (errno
== ENOPROTOOPT
)
290 log(L_ERR
"Kernel does not support IPv4 TTL security");
292 log(L_ERR
"sk_set_min_ttl4: setsockopt: %m");
303 sk_set_min_ttl6(sock
*s
, int ttl
)
305 log(L_ERR
"IPv6 TTL security not supported");
312 int sk_priority_control
= -1;
315 sk_set_priority(sock
*s
, int prio UNUSED
)
317 log(L_WARN
"Socket priority not supported");