Annotation of embedaddon/bird2/sysdep/bsd/sysio.h, revision 1.1

1.1     ! misho       1: /*
        !             2:  *     BIRD Internet Routing Daemon -- BSD Multicasting and Network Includes
        !             3:  *
        !             4:  *     (c) 2004       Ondrej Filip <feela@network.cz>
        !             5:  *
        !             6:  *     Can be freely distributed and used under the terms of the GNU GPL.
        !             7:  */
        !             8: 
        !             9: #include <net/if_dl.h>
        !            10: #include <netinet/in_systm.h> // Workaround for some BSDs
        !            11: #include <netinet/ip.h>
        !            12: #include <sys/param.h>
        !            13: 
        !            14: 
        !            15: #ifdef __FreeBSD__
        !            16: /* Should be defined in sysdep/cf/bsd.h, but it is flavor-specific */
        !            17: #define CONFIG_DONTROUTE_UNICAST
        !            18: #endif
        !            19: 
        !            20: #ifdef __NetBSD__
        !            21: 
        !            22: #ifndef IP_RECVTTL
        !            23: #define IP_RECVTTL 23
        !            24: #endif
        !            25: 
        !            26: #ifndef IP_MINTTL
        !            27: #define IP_MINTTL 24
        !            28: #endif
        !            29: 
        !            30: #endif
        !            31: 
        !            32: #ifdef __DragonFly__
        !            33: #define TCP_MD5SIG     TCP_SIGNATURE_ENABLE
        !            34: #endif
        !            35: 
        !            36: 
        !            37: #undef  SA_LEN
        !            38: #define SA_LEN(x) (x).sa.sa_len
        !            39: 
        !            40: 
        !            41: /*
        !            42:  *     BSD IPv4 multicast syscalls
        !            43:  */
        !            44: 
        !            45: #define INIT_MREQ4(maddr,ifa) \
        !            46:   { .imr_multiaddr = ipa_to_in4(maddr), .imr_interface = ip4_to_in4(ifa->sysdep) }
        !            47: 
        !            48: static inline int
        !            49: sk_setup_multicast4(sock *s)
        !            50: {
        !            51:   struct in_addr ifa = ip4_to_in4(s->iface->sysdep);
        !            52:   u8 ttl = s->ttl;
        !            53:   u8 n = 0;
        !            54: 
        !            55:   /* This defines where should we send _outgoing_ multicasts */
        !            56:   if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_IF, &ifa, sizeof(ifa)) < 0)
        !            57:     ERR("IP_MULTICAST_IF");
        !            58: 
        !            59:   if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
        !            60:     ERR("IP_MULTICAST_TTL");
        !            61: 
        !            62:   if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &n, sizeof(n)) < 0)
        !            63:     ERR("IP_MULTICAST_LOOP");
        !            64: 
        !            65:   return 0;
        !            66: }
        !            67: 
        !            68: static inline int
        !            69: sk_join_group4(sock *s, ip_addr maddr)
        !            70: {
        !            71:   struct ip_mreq mr = INIT_MREQ4(maddr, s->iface);
        !            72: 
        !            73:   if (setsockopt(s->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mr, sizeof(mr)) < 0)
        !            74:     ERR("IP_ADD_MEMBERSHIP");
        !            75: 
        !            76:   return 0;
        !            77: }
        !            78: 
        !            79: static inline int
        !            80: sk_leave_group4(sock *s, ip_addr maddr)
        !            81: {
        !            82:   struct ip_mreq mr = INIT_MREQ4(maddr, s->iface);
        !            83: 
        !            84:   if (setsockopt(s->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mr, sizeof(mr)) < 0)
        !            85:     ERR("IP_ADD_MEMBERSHIP");
        !            86: 
        !            87:   return 0;
        !            88: }
        !            89: 
        !            90: 
        !            91: /*
        !            92:  *     BSD IPv4 packet control messages
        !            93:  */
        !            94: 
        !            95: /* It uses IP_RECVDSTADDR / IP_RECVIF socket options instead of IP_PKTINFO */
        !            96: 
        !            97: #define CMSG4_SPACE_PKTINFO (CMSG_SPACE(sizeof(struct in_addr)) + \
        !            98:                             CMSG_SPACE(sizeof(struct sockaddr_dl)))
        !            99: #define CMSG4_SPACE_TTL CMSG_SPACE(sizeof(char))
        !           100: 
        !           101: static inline int
        !           102: sk_request_cmsg4_pktinfo(sock *s)
        !           103: {
        !           104:   int y = 1;
        !           105: 
        !           106:   if (setsockopt(s->fd, IPPROTO_IP, IP_RECVDSTADDR, &y, sizeof(y)) < 0)
        !           107:     ERR("IP_RECVDSTADDR");
        !           108: 
        !           109:   if (setsockopt(s->fd, IPPROTO_IP, IP_RECVIF, &y, sizeof(y)) < 0)
        !           110:     ERR("IP_RECVIF");
        !           111: 
        !           112:   return 0;
        !           113: }
        !           114: 
        !           115: static inline int
        !           116: sk_request_cmsg4_ttl(sock *s)
        !           117: {
        !           118:   int y = 1;
        !           119: 
        !           120:   if (setsockopt(s->fd, IPPROTO_IP, IP_RECVTTL, &y, sizeof(y)) < 0)
        !           121:     ERR("IP_RECVTTL");
        !           122: 
        !           123:   return 0;
        !           124: }
        !           125: 
        !           126: static inline void
        !           127: sk_process_cmsg4_pktinfo(sock *s, struct cmsghdr *cm)
        !           128: {
        !           129:   if (cm->cmsg_type == IP_RECVDSTADDR)
        !           130:     s->laddr = ipa_from_in4(* (struct in_addr *) CMSG_DATA(cm));
        !           131: 
        !           132:   if (cm->cmsg_type == IP_RECVIF)
        !           133:     s->lifindex = ((struct sockaddr_dl *) CMSG_DATA(cm))->sdl_index;
        !           134: }
        !           135: 
        !           136: static inline void
        !           137: sk_process_cmsg4_ttl(sock *s, struct cmsghdr *cm)
        !           138: {
        !           139:   if (cm->cmsg_type == IP_RECVTTL)
        !           140:     s->rcv_ttl = * (byte *) CMSG_DATA(cm);
        !           141: }
        !           142: 
        !           143: #ifdef IP_SENDSRCADDR
        !           144: static inline void
        !           145: sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
        !           146: {
        !           147:   /* Unfortunately, IP_SENDSRCADDR does not work for raw IP sockets on BSD kernels */
        !           148: 
        !           149:   struct cmsghdr *cm;
        !           150:   struct in_addr *sa;
        !           151:   int controllen = 0;
        !           152: 
        !           153:   msg->msg_control = cbuf;
        !           154:   msg->msg_controllen = cbuflen;
        !           155: 
        !           156:   cm = CMSG_FIRSTHDR(msg);
        !           157:   cm->cmsg_level = IPPROTO_IP;
        !           158:   cm->cmsg_type = IP_SENDSRCADDR;
        !           159:   cm->cmsg_len = CMSG_LEN(sizeof(*sa));
        !           160:   controllen += CMSG_SPACE(sizeof(*sa));
        !           161: 
        !           162:   sa = (struct in_addr *) CMSG_DATA(cm);
        !           163:   *sa = ipa_to_in4(s->saddr);
        !           164: 
        !           165:   msg->msg_controllen = controllen;
        !           166: }
        !           167: #else
        !           168: static inline void
        !           169: sk_prepare_cmsgs4(sock *s UNUSED, struct msghdr *msg UNUSED, void *cbuf UNUSED, size_t cbuflen UNUSED) { }
        !           170: #endif
        !           171: 
        !           172: static void UNUSED
        !           173: sk_prepare_ip_header(sock *s, void *hdr, int dlen)
        !           174: {
        !           175:   struct ip *ip = hdr;
        !           176: 
        !           177:   bzero(ip, 20);
        !           178: 
        !           179:   ip->ip_v = 4;
        !           180:   ip->ip_hl = 5;
        !           181:   ip->ip_tos = (s->tos < 0) ? 0 : s->tos;
        !           182:   ip->ip_len = 20 + dlen;
        !           183:   ip->ip_ttl = (s->ttl < 0) ? 64 : s->ttl;
        !           184:   ip->ip_p = s->dport;
        !           185:   ip->ip_src = ipa_to_in4(s->saddr);
        !           186:   ip->ip_dst = ipa_to_in4(s->daddr);
        !           187: 
        !           188: #if (defined __OpenBSD__) || (defined __DragonFly__) || (defined __FreeBSD__ && (__FreeBSD_version >= 1100030))
        !           189:   /* Different BSDs have different expectations of ip_len endianity */
        !           190:   ip->ip_len = htons(ip->ip_len);
        !           191: #endif
        !           192: }
        !           193: 
        !           194: 
        !           195: /*
        !           196:  *     Miscellaneous BSD socket syscalls
        !           197:  */
        !           198: 
        !           199: #ifndef TCP_KEYLEN_MAX
        !           200: #define TCP_KEYLEN_MAX 80
        !           201: #endif
        !           202: 
        !           203: #ifndef TCP_SIG_SPI
        !           204: #define TCP_SIG_SPI 0x1000
        !           205: #endif
        !           206: 
        !           207: #if defined(__FreeBSD__)
        !           208: #define USE_MD5SIG_SETKEY
        !           209: #include "sysdep/bsd/setkey.h"
        !           210: #endif
        !           211: 
        !           212: int
        !           213: sk_set_md5_auth(sock *s, ip_addr local UNUSED, ip_addr remote UNUSED, struct iface *ifa UNUSED, char *passwd, int setkey UNUSED)
        !           214: {
        !           215: #ifdef USE_MD5SIG_SETKEY
        !           216:   if (setkey)
        !           217:     if (sk_set_md5_in_sasp_db(s, local, remote, ifa, passwd) < 0)
        !           218:       return -1;
        !           219: #endif
        !           220: 
        !           221:   int enable = (passwd && *passwd) ? TCP_SIG_SPI : 0;
        !           222:   if (setsockopt(s->fd, IPPROTO_TCP, TCP_MD5SIG, &enable, sizeof(enable)) < 0)
        !           223:   {
        !           224:     if (errno == ENOPROTOOPT)
        !           225:       ERR_MSG("Kernel does not support TCP MD5 signatures");
        !           226:     else
        !           227:       ERR("TCP_MD5SIG");
        !           228:   }
        !           229: 
        !           230:   return 0;
        !           231: }
        !           232: 
        !           233: static inline int
        !           234: sk_set_min_ttl4(sock *s, int ttl)
        !           235: {
        !           236:   if (setsockopt(s->fd, IPPROTO_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0)
        !           237:   {
        !           238:     if (errno == ENOPROTOOPT)
        !           239:       ERR_MSG("Kernel does not support IPv4 TTL security");
        !           240:     else
        !           241:       ERR("IP_MINTTL");
        !           242:   }
        !           243: 
        !           244:   return 0;
        !           245: }
        !           246: 
        !           247: static inline int
        !           248: sk_set_min_ttl6(sock *s, int ttl UNUSED)
        !           249: {
        !           250:   ERR_MSG("Kernel does not support IPv6 TTL security");
        !           251: }
        !           252: 
        !           253: static inline int
        !           254: sk_disable_mtu_disc4(sock *s UNUSED)
        !           255: {
        !           256:   /* TODO: Set IP_DONTFRAG to 0 ? */
        !           257:   return 0;
        !           258: }
        !           259: 
        !           260: static inline int
        !           261: sk_disable_mtu_disc6(sock *s UNUSED)
        !           262: {
        !           263:   /* TODO: Set IPV6_DONTFRAG to 0 ? */
        !           264:   return 0;
        !           265: }
        !           266: 
        !           267: int sk_priority_control = -1;
        !           268: 
        !           269: static inline int
        !           270: sk_set_priority(sock *s, int prio UNUSED)
        !           271: {
        !           272:   ERR_MSG("Socket priority not supported");
        !           273: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>