Annotation of embedaddon/bird/sysdep/linux/sysio.h, revision 1.1
1.1 ! misho 1: /*
! 2: * BIRD Internet Routing Daemon -- Linux Multicasting and Network Includes
! 3: *
! 4: * (c) 1998--2000 Martin Mares <mj@ucw.cz>
! 5: *
! 6: * Can be freely distributed and used under the terms of the GNU GPL.
! 7: */
! 8:
! 9:
! 10: #ifndef HAVE_STRUCT_IP_MREQN
! 11: /* Several versions of glibc don't define this structure, so we have to do it ourselves */
! 12: struct ip_mreqn
! 13: {
! 14: struct in_addr imr_multiaddr; /* IP multicast address of group */
! 15: struct in_addr imr_address; /* local IP address of interface */
! 16: int imr_ifindex; /* Interface index */
! 17: };
! 18: #endif
! 19:
! 20: #ifndef IP_MINTTL
! 21: #define IP_MINTTL 21
! 22: #endif
! 23:
! 24: #ifndef IPV6_TCLASS
! 25: #define IPV6_TCLASS 67
! 26: #endif
! 27:
! 28: #ifndef IPV6_MINHOPCOUNT
! 29: #define IPV6_MINHOPCOUNT 73
! 30: #endif
! 31:
! 32:
! 33: #ifndef TCP_MD5SIG
! 34:
! 35: #define TCP_MD5SIG 14
! 36: #define TCP_MD5SIG_MAXKEYLEN 80
! 37:
! 38: struct tcp_md5sig {
! 39: struct sockaddr_storage tcpm_addr; /* address associated */
! 40: u16 __tcpm_pad1; /* zero */
! 41: u16 tcpm_keylen; /* key length */
! 42: u32 __tcpm_pad2; /* zero */
! 43: u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN]; /* key (binary) */
! 44: };
! 45:
! 46: #endif
! 47:
! 48:
! 49: /* Linux does not care if sa_len is larger than needed */
! 50: #define SA_LEN(x) sizeof(sockaddr)
! 51:
! 52:
! 53: /*
! 54: * Linux IPv4 multicast syscalls
! 55: */
! 56:
! 57: #define INIT_MREQ4(maddr,ifa) \
! 58: { .imr_multiaddr = ipa_to_in4(maddr), .imr_ifindex = ifa->index }
! 59:
! 60: static inline int
! 61: sk_setup_multicast4(sock *s)
! 62: {
! 63: struct ip_mreqn mr = { .imr_ifindex = s->iface->index };
! 64: int ttl = s->ttl;
! 65: int n = 0;
! 66:
! 67: /* This defines where should we send _outgoing_ multicasts */
! 68: if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_IF, &mr, sizeof(mr)) < 0)
! 69: ERR("IP_MULTICAST_IF");
! 70:
! 71: if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
! 72: ERR("IP_MULTICAST_TTL");
! 73:
! 74: if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_LOOP, &n, sizeof(n)) < 0)
! 75: ERR("IP_MULTICAST_LOOP");
! 76:
! 77: return 0;
! 78: }
! 79:
! 80: static inline int
! 81: sk_join_group4(sock *s, ip_addr maddr)
! 82: {
! 83: struct ip_mreqn mr = INIT_MREQ4(maddr, s->iface);
! 84:
! 85: if (setsockopt(s->fd, SOL_IP, IP_ADD_MEMBERSHIP, &mr, sizeof(mr)) < 0)
! 86: ERR("IP_ADD_MEMBERSHIP");
! 87:
! 88: return 0;
! 89: }
! 90:
! 91: static inline int
! 92: sk_leave_group4(sock *s, ip_addr maddr)
! 93: {
! 94: struct ip_mreqn mr = INIT_MREQ4(maddr, s->iface);
! 95:
! 96: if (setsockopt(s->fd, SOL_IP, IP_DROP_MEMBERSHIP, &mr, sizeof(mr)) < 0)
! 97: ERR("IP_DROP_MEMBERSHIP");
! 98:
! 99: return 0;
! 100: }
! 101:
! 102:
! 103: /*
! 104: * Linux IPv4 packet control messages
! 105: */
! 106:
! 107: /* Mostly similar to standardized IPv6 code */
! 108:
! 109: #define CMSG4_SPACE_PKTINFO CMSG_SPACE(sizeof(struct in_pktinfo))
! 110: #define CMSG4_SPACE_TTL CMSG_SPACE(sizeof(int))
! 111:
! 112: static inline int
! 113: sk_request_cmsg4_pktinfo(sock *s)
! 114: {
! 115: int y = 1;
! 116:
! 117: if (setsockopt(s->fd, SOL_IP, IP_PKTINFO, &y, sizeof(y)) < 0)
! 118: ERR("IP_PKTINFO");
! 119:
! 120: return 0;
! 121: }
! 122:
! 123: static inline int
! 124: sk_request_cmsg4_ttl(sock *s)
! 125: {
! 126: int y = 1;
! 127:
! 128: if (setsockopt(s->fd, SOL_IP, IP_RECVTTL, &y, sizeof(y)) < 0)
! 129: ERR("IP_RECVTTL");
! 130:
! 131: return 0;
! 132: }
! 133:
! 134: static inline void
! 135: sk_process_cmsg4_pktinfo(sock *s, struct cmsghdr *cm)
! 136: {
! 137: if (cm->cmsg_type == IP_PKTINFO)
! 138: {
! 139: struct in_pktinfo *pi = (struct in_pktinfo *) CMSG_DATA(cm);
! 140: s->laddr = ipa_from_in4(pi->ipi_addr);
! 141: s->lifindex = pi->ipi_ifindex;
! 142: }
! 143: }
! 144:
! 145: static inline void
! 146: sk_process_cmsg4_ttl(sock *s, struct cmsghdr *cm)
! 147: {
! 148: if (cm->cmsg_type == IP_TTL)
! 149: s->rcv_ttl = * (int *) CMSG_DATA(cm);
! 150: }
! 151:
! 152: static inline void
! 153: sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
! 154: {
! 155: struct cmsghdr *cm;
! 156: struct in_pktinfo *pi;
! 157: int controllen = 0;
! 158:
! 159: msg->msg_control = cbuf;
! 160: msg->msg_controllen = cbuflen;
! 161:
! 162: cm = CMSG_FIRSTHDR(msg);
! 163: cm->cmsg_level = SOL_IP;
! 164: cm->cmsg_type = IP_PKTINFO;
! 165: cm->cmsg_len = CMSG_LEN(sizeof(*pi));
! 166: controllen += CMSG_SPACE(sizeof(*pi));
! 167:
! 168: pi = (struct in_pktinfo *) CMSG_DATA(cm);
! 169: pi->ipi_ifindex = s->iface ? s->iface->index : 0;
! 170: pi->ipi_spec_dst = ipa_to_in4(s->saddr);
! 171: pi->ipi_addr = ipa_to_in4(IPA_NONE);
! 172:
! 173: msg->msg_controllen = controllen;
! 174: }
! 175:
! 176:
! 177: /*
! 178: * Miscellaneous Linux socket syscalls
! 179: */
! 180:
! 181: int
! 182: sk_set_md5_auth(sock *s, ip_addr local UNUSED, ip_addr remote, struct iface *ifa, char *passwd, int setkey UNUSED)
! 183: {
! 184: struct tcp_md5sig md5;
! 185:
! 186: memset(&md5, 0, sizeof(md5));
! 187: sockaddr_fill((sockaddr *) &md5.tcpm_addr, s->af, remote, ifa, 0);
! 188:
! 189: if (passwd)
! 190: {
! 191: int len = strlen(passwd);
! 192:
! 193: if (len > TCP_MD5SIG_MAXKEYLEN)
! 194: ERR_MSG("The password for TCP MD5 Signature is too long");
! 195:
! 196: md5.tcpm_keylen = len;
! 197: memcpy(&md5.tcpm_key, passwd, len);
! 198: }
! 199:
! 200: if (setsockopt(s->fd, SOL_TCP, TCP_MD5SIG, &md5, sizeof(md5)) < 0)
! 201: {
! 202: if (errno == ENOPROTOOPT)
! 203: ERR_MSG("Kernel does not support TCP MD5 signatures");
! 204: else
! 205: ERR("TCP_MD5SIG");
! 206: }
! 207:
! 208: return 0;
! 209: }
! 210:
! 211: static inline int
! 212: sk_set_min_ttl4(sock *s, int ttl)
! 213: {
! 214: if (setsockopt(s->fd, SOL_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0)
! 215: {
! 216: if (errno == ENOPROTOOPT)
! 217: ERR_MSG("Kernel does not support IPv4 TTL security");
! 218: else
! 219: ERR("IP_MINTTL");
! 220: }
! 221:
! 222: return 0;
! 223: }
! 224:
! 225: static inline int
! 226: sk_set_min_ttl6(sock *s, int ttl)
! 227: {
! 228: if (setsockopt(s->fd, SOL_IPV6, IPV6_MINHOPCOUNT, &ttl, sizeof(ttl)) < 0)
! 229: {
! 230: if (errno == ENOPROTOOPT)
! 231: ERR_MSG("Kernel does not support IPv6 TTL security");
! 232: else
! 233: ERR("IPV6_MINHOPCOUNT");
! 234: }
! 235:
! 236: return 0;
! 237: }
! 238:
! 239: static inline int
! 240: sk_disable_mtu_disc4(sock *s)
! 241: {
! 242: int dont = IP_PMTUDISC_DONT;
! 243:
! 244: if (setsockopt(s->fd, SOL_IP, IP_MTU_DISCOVER, &dont, sizeof(dont)) < 0)
! 245: ERR("IP_MTU_DISCOVER");
! 246:
! 247: return 0;
! 248: }
! 249:
! 250: static inline int
! 251: sk_disable_mtu_disc6(sock *s)
! 252: {
! 253: int dont = IPV6_PMTUDISC_DONT;
! 254:
! 255: if (setsockopt(s->fd, SOL_IPV6, IPV6_MTU_DISCOVER, &dont, sizeof(dont)) < 0)
! 256: ERR("IPV6_MTU_DISCOVER");
! 257:
! 258: return 0;
! 259: }
! 260:
! 261: int sk_priority_control = 7;
! 262:
! 263: static inline int
! 264: sk_set_priority(sock *s, int prio)
! 265: {
! 266: if (setsockopt(s->fd, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio)) < 0)
! 267: ERR("SO_PRIORITY");
! 268:
! 269: return 0;
! 270: }
! 271:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>