PRIVATE_EXTERN RTADVSocketRef RTADVSocketCreate(interface_t * if_p) { RTADVSocketRef sock; RTADVSocketGlobalsRef globals; globals = RTADVSocketGetGlobals(); if (globals == NULL) { my_log(LOG_NOTICE, "RTADVSocketCreate: could not allocate globals"); return (NULL); } sock = RTADVSocketFind(if_link_index(if_p)); if (sock != NULL) { my_log(LOG_NOTICE, "RTADVSocketCreate(%s): socket already allocated", if_name(if_p)); return (NULL); } sock = malloc(sizeof(*sock)); if (sock == NULL) { return (NULL); } bzero(sock, sizeof(*sock)); if (dynarray_add(&globals->sockets, sock) == FALSE) { free(sock); return (NULL); } sock->if_p = if_p; return (sock); }
PRIVATE_EXTERN int RTADVSocketSendSolicitation(RTADVSocketRef sock, bool lladdr_ok) { interface_t * if_p = RTADVSocketGetInterface(sock); boolean_t needs_close = FALSE; int ret; uint32_t txbuf[RTSOL_PACKET_MAX / sizeof(uint32_t)]; int txbuf_used; /* amount actually used */ if (sock->fd_open == FALSE) { /* open the RTADV socket in case it's needed */ if (RTADVSocketOpenSocket(sock) == FALSE) { my_log(LOG_NOTICE, "RTADVSocket: failed to open socket"); return (FALSE); } needs_close = TRUE; } txbuf_used = RTADVSocketInitTXBuf(sock, txbuf, lladdr_ok); ret = IPv6SocketSend(FDCalloutGetFD(S_globals->read_fd), if_link_index(if_p), &sin6_allrouters, (void *)txbuf, txbuf_used, ND_RTADV_HOP_LIMIT); if (needs_close) { RTADVSocketCloseSocket(sock); } return (ret); }
STATIC RTADVSocketRef RTADVSocketFind(int if_index) { int i; for (i = 0; i < dynarray_count(&S_globals->sockets); i++) { interface_t * if_p; RTADVSocketRef sock; sock = dynarray_element(&S_globals->sockets, i); if_p = RTADVSocketGetInterface(sock); if (if_index == if_link_index(if_p)) { return (sock); } } return (NULL); }
static void DHCPv6SocketDemux(int if_index, const DHCPv6PacketRef pkt, int pkt_len) { DHCPv6SocketReceiveData data; DHCPv6OptionErrorString err; int i; if (pkt_len < DHCPV6_PACKET_HEADER_LENGTH) { return; } data.pkt = pkt; data.pkt_len = pkt_len; data.options = DHCPv6OptionListCreateWithPacket(pkt, pkt_len, &err); if (data.options == NULL) { my_log(LOG_NOTICE, "DHCPv6Socket: options parse failed, %s", err.str); return; } for (i = 0; i < dynarray_count(&S_globals->sockets); i++) { DHCPv6SocketRef client; client = dynarray_element(&S_globals->sockets, i); if (if_index != if_link_index(DHCPv6SocketGetInterface(client))) { continue; } if (S_verbose) { CFMutableStringRef str; str = CFStringCreateMutable(NULL, 0); DHCPv6PacketPrintToString(str, pkt, pkt_len); if (data.options != NULL) { DHCPv6OptionListPrintToString(str, data.options); } my_log(-LOG_DEBUG, "[%s] Receive %@", if_name(DHCPv6SocketGetInterface(client)), str); CFRelease(str); } if (client->receive_func != NULL) { (*client->receive_func)(client->receive_arg1, client->receive_arg2, &data); } } DHCPv6OptionListRelease(&data.options); return; }
int DHCPv6SocketTransmit(DHCPv6SocketRef sock, DHCPv6PacketRef pkt, int pkt_len) { DHCPv6OptionErrorString err; int ret; boolean_t needs_close = FALSE; if (sock->fd_open == FALSE) { /* open the DHCPv6 socket in case it's needed */ if (DHCPv6SocketOpenSocket(sock) == FALSE) { my_log(LOG_ERR, "DHCPv6Socket: failed to open socket"); return (FALSE); } needs_close = TRUE; } if (S_verbose) { DHCPv6OptionListRef options; CFMutableStringRef str; str = CFStringCreateMutable(NULL, 0); DHCPv6PacketPrintToString(str, pkt, pkt_len); options = DHCPv6OptionListCreateWithPacket(pkt, pkt_len, &err); if (options == NULL) { my_log_fl(LOG_DEBUG, "parse options failed, %s", err.str); } else { DHCPv6OptionListPrintToString(str, options); DHCPv6OptionListRelease(&options); } my_log(-LOG_DEBUG,"[%s] Transmit %@", if_name(sock->if_p), str); CFRelease(str); } ret = S_send_packet(FDCalloutGetFD(S_globals->read_fd), if_link_index(sock->if_p), pkt, pkt_len); if (needs_close) { DHCPv6SocketCloseSocket(sock); } return (ret); }