/* Generate (what we hope is) a true random byte using /dev/urandom */ static u_char generate_rnd_byte(void) { u_char c; if (read(random_fd, &c, sizeof(c)) == -1) exit_log_errno((e, "read() failed in get_rnd_byte()")); return c; }
/** init_netlink - Initialize the netlink inferface. Opens the sockets and * then binds to the broadcast socket. */ static void init_netlink(void) { struct sockaddr_nl addr; netlinkfd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_XFRM); if (netlinkfd < 0) exit_log_errno((e, "socket() in init_netlink()")); if (fcntl(netlinkfd, F_SETFD, FD_CLOEXEC) != 0) exit_log_errno((e, "fcntl(FD_CLOEXEC) in init_netlink()")); netlink_bcast_fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_XFRM); if (netlink_bcast_fd < 0) exit_log_errno((e, "socket() for bcast in init_netlink()")); if (fcntl(netlink_bcast_fd, F_SETFD, FD_CLOEXEC) != 0) exit_log_errno((e, "fcntl(FD_CLOEXEC) for bcast in init_netlink()")); if (fcntl(netlink_bcast_fd, F_SETFL, O_NONBLOCK) != 0) exit_log_errno((e, "fcntl(O_NONBLOCK) for bcast in init_netlink()")); addr.nl_family = AF_NETLINK; addr.nl_pid = getpid(); addr.nl_groups = XFRMGRP_ACQUIRE | XFRMGRP_EXPIRE; if (bind(netlink_bcast_fd, (struct sockaddr *)&addr, sizeof(addr)) != 0) exit_log_errno((e, "Failed to bind bcast socket in init_netlink()")); }
void init_pfkey(void) { pid = getpid(); /* open PF_KEY socket */ pfkeyfd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2); if (pfkeyfd == -1) exit_log_errno((e, "socket() in init_pfkeyfd()")); #ifdef NEVER /* apparently unsupported! */ if (fcntl(pfkeyfd, F_SETFL, O_NONBLOCK) != 0) exit_log_errno((e, "fcntl(O_NONBLOCK) in init_pfkeyfd()")); #endif if (fcntl(pfkeyfd, F_SETFD, FD_CLOEXEC) != 0) exit_log_errno((e, "fcntl(FD_CLOEXEC) in init_pfkeyfd()")); DBG(DBG_KLIPS, DBG_log("process %u listening for PF_KEY_V2 on file descriptor %d", (unsigned)pid, pfkeyfd)); }
/* * Initialize the random pool. */ void init_rnd_pool(void) { #ifndef USE_ARC4RANDOM # ifdef USE_DEV_RANDOM DBG(DBG_KLIPS, DBG_log("opening %s", RANDOM_PATH)); random_fd = open(RANDOM_PATH, O_RDONLY); if (random_fd == -1) exit_log_errno((e, "open of %s failed in init_rnd_pool()", RANDOM_PATH)); fcntl(random_fd, F_SETFD, FD_CLOEXEC); # endif get_rnd_bytes(random_pool, RANDOM_POOL_SIZE); mix_pool(); #endif /* !USE_ARC4RANDOM */ /* start of rand(3) on the right foot */ { unsigned int seed; get_rnd_bytes((void *)&seed, sizeof(seed)); srand(seed); } }
struct raw_iface * find_raw_ifaces4(void) { static const int on = TRUE; /* by-reference parameter; constant, we hope */ int j; /* index into buf */ static int num=64; /* number of interfaces */ struct ifconf ifconf; struct ifreq *buf; /* for list of interfaces -- arbitrary limit */ struct raw_iface *rifaces = NULL; int master_sock = safe_socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); /* Get a UDP socket */ /* get list of interfaces with assigned IPv4 addresses from system */ if (master_sock == -1) exit_log_errno((e, "socket() failed in find_raw_ifaces4()")); if (setsockopt(master_sock, SOL_SOCKET, SO_REUSEADDR , (const void *)&on, sizeof(on)) < 0) exit_log_errno((e, "setsockopt() in find_raw_ifaces4()")); /* bind the socket */ { ip_address any; happy(anyaddr(AF_INET, &any)); setportof(htons(pluto_port), &any); if (bind(master_sock, sockaddrof(&any), sockaddrlenof(&any)) < 0) exit_log_errno((e, "bind() failed in find_raw_ifaces4()")); } buf = NULL; /* a million interfaces is probably the maximum, ever... */ while(num < (1024*1024)) { /* Get local interfaces. See netdevice(7). */ ifconf.ifc_len = num * sizeof(struct ifreq); buf = (void *) realloc(buf, ifconf.ifc_len); if (!buf) exit_log_errno((e, "realloc of %d in find_raw_ifaces4()", ifconf.ifc_len)); memset(buf, 0, num*sizeof(struct ifreq)); ifconf.ifc_buf = (void *) buf; if (ioctl(master_sock, SIOCGIFCONF, &ifconf) == -1) exit_log_errno((e, "ioctl(SIOCGIFCONF) in find_raw_ifaces4()")); /* if we got back less than we asked for, we have them all */ if (ifconf.ifc_len < (int)(sizeof(struct ifreq) * num)) break; /* try again and ask for more this time */ num *= 2; } /* Add an entry to rifaces for each interesting interface. */ for (j = 0; (j+1) * sizeof(struct ifreq) <= (size_t)ifconf.ifc_len; j++) { struct raw_iface ri; const struct sockaddr_in *rs = (struct sockaddr_in *) &buf[j].ifr_addr; struct ifreq auxinfo; /* ignore all but AF_INET interfaces */ if (rs->sin_family != AF_INET) continue; /* not interesting */ /* build a NUL-terminated copy of the rname field */ memcpy(ri.name, buf[j].ifr_name, IFNAMSIZ); ri.name[IFNAMSIZ] = '\0'; /* ignore if our interface names were specified, and this isn't one */ if (pluto_ifn_roof != 0) { int i; for (i = 0; i != pluto_ifn_roof; i++) if (streq(ri.name, pluto_ifn[i])) break; if (i == pluto_ifn_roof) continue; /* not found -- skip */ } /* Find out stuff about this interface. See netdevice(7). */ zero(&auxinfo); /* paranoia */ memcpy(auxinfo.ifr_name, buf[j].ifr_name, IFNAMSIZ); if (ioctl(master_sock, SIOCGIFFLAGS, &auxinfo) == -1) exit_log_errno((e , "ioctl(SIOCGIFFLAGS) for %s in find_raw_ifaces4()" , ri.name)); if (!(auxinfo.ifr_flags & IFF_UP)) { DBG(DBG_CONTROL, DBG_log("Ignored interface %s - it is not up" , ri.name)); continue; /* ignore an interface that isn't UP */ } if (auxinfo.ifr_flags & IFF_SLAVE) { DBG(DBG_CONTROL, DBG_log("Ignored interface %s - it is a slave interface" , ri.name)); continue; /* ignore slave interfaces; they share IPs with their master */ } /* ignore unconfigured interfaces */ if (rs->sin_addr.s_addr == 0) { DBG(DBG_CONTROL, DBG_log("Ignored interface %s - it is unconfigured" , ri.name)); continue; } happy(initaddr((const void *)&rs->sin_addr, sizeof(struct in_addr) , AF_INET, &ri.addr)); DBG(DBG_CONTROL, DBG_log("found %s with address %s" , ri.name, ip_str(&ri.addr))); ri.next = rifaces; rifaces = clone_thing(ri, "struct raw_iface"); } close(master_sock); return rifaces; }
struct raw_iface *find_raw_ifaces4(void) { static const int on = TRUE; /* by-reference parameter; constant, we hope */ int j; /* index into buf */ struct ifconf ifconf; struct ifreq *buf = NULL; /* for list of interfaces -- arbitrary limit */ struct ifreq *bp; /* cursor into buf */ struct raw_iface *rifaces = NULL; int master_sock = safe_socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); /* Get a UDP socket */ /* * Current upper bound on number of interfaces. * Tricky: because this is a static, we won't have to start from * 64 in subsequent calls. */ static int num = 64; /* number of interfaces */ /* get list of interfaces with assigned IPv4 addresses from system */ if (master_sock == -1) exit_log_errno((e, "socket() failed in find_raw_ifaces4()")); if (setsockopt(master_sock, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof(on)) < 0) exit_log_errno((e, "setsockopt() in find_raw_ifaces4()")); /* bind the socket */ { ip_address any; happy(anyaddr(AF_INET, &any)); setportof(htons(pluto_port), &any); if (bind(master_sock, sockaddrof(&any), sockaddrlenof(&any)) < 0) exit_log_errno((e, "bind() failed in find_raw_ifaces4()")); } /* a million interfaces is probably the maximum, ever... */ for (; num < (1024 * 1024); num *= 2) { /* Get num local interfaces. See netdevice(7). */ ifconf.ifc_len = num * sizeof(struct ifreq); buf = realloc(buf, ifconf.ifc_len); if (buf == NULL) { exit_log_errno((e, "realloc of %d in find_raw_ifaces4()", ifconf.ifc_len)); } memset(buf, 0xDF, ifconf.ifc_len); /* stomp */ ifconf.ifc_buf = (void *) buf; if (ioctl(master_sock, SIOCGIFCONF, &ifconf) == -1) exit_log_errno((e, "ioctl(SIOCGIFCONF) in find_raw_ifaces4()")); /* if we got back less than we asked for, we have them all */ if (ifconf.ifc_len < (int)(sizeof(struct ifreq) * num)) break; } /* Add an entry to rifaces for each interesting interface. On Apple, the size of struct ifreq depends on the contents of the union. See if.h */ for (bp = buf, j = 0; bp < (unsigned char *)buf + (size_t)ifconf.ifc_len; bp = (struct ifreq *) ((unsigned char *)bp +_SIZEOF_ADDR_IFREQ(*bp)), j++) { struct raw_iface ri; const struct sockaddr_in *rs = (struct sockaddr_in *) &bp->ifr_addr; struct ifreq auxinfo; /* ignore all but AF_INET interfaces */ if (rs->sin_family != AF_INET) continue; /* not interesting */ /* build a NUL-terminated copy of the rname field */ memcpy(ri.name, bp->ifr_name, IFNAMSIZ); ri.name[IFNAMSIZ] = '\0'; /* ignore if our interface names were specified, and this isn't one */ if (pluto_ifn_roof != 0) { int i; for (i = 0; i != pluto_ifn_roof; i++) if (streq(ri.name, pluto_ifn[i])) break; if (i == pluto_ifn_roof) continue; /* not found -- skip */ } /* Find out stuff about this interface. See netdevice(7). */ zero(&auxinfo); /* paranoia */ memcpy(auxinfo.ifr_name, bp->ifr_name, IFNAMSIZ); if (ioctl(master_sock, SIOCGIFFLAGS, &auxinfo) == -1) { exit_log_errno((e, "ioctl(SIOCGIFFLAGS) for %s in find_raw_ifaces4()", ri.name)); } if (!(auxinfo.ifr_flags & IFF_UP)) continue; /* ignore an interface that isn't UP */ /* ignore unconfigured interfaces */ if (rs->sin_addr.s_addr == 0) continue; happy(initaddr((const void *)&rs->sin_addr, sizeof(struct in_addr), AF_INET, &ri.addr)); DBG(DBG_CONTROL, { ipstr_buf b; DBG_log("found %s with address %s", ri.name, ipstr(&ri.addr, &b)); }); ri.next = rifaces; rifaces = clone_thing(ri, "struct raw_iface"); }