_public_ struct knot_request *knot_request_make(mm_ctx_t *mm, const struct sockaddr *dst, const struct sockaddr *src, knot_pkt_t *query, unsigned flags) { if (dst == NULL || query == NULL) { return NULL; } /* Form a pending request. */ struct knot_request *request = request_make(mm); if (request == NULL) { return NULL; } memcpy(&request->remote, dst, sockaddr_len(dst)); if (src) { memcpy(&request->origin, src, sockaddr_len(src)); } else { request->origin.ss_family = AF_UNSPEC; } request->fd = -1; request->query = query; request->resp = NULL; request->flags = flags; return request; }
static char *addr_toname(const scamper_addr_t *addr, char *buf, size_t len) { struct sockaddr *sa = NULL; struct sockaddr_in in4; struct sockaddr_in6 in6; socklen_t sl; if(SCAMPER_ADDR_TYPE_IS_IPV4(addr)) { sockaddr_compose((struct sockaddr *)&in4, AF_INET, addr->addr, 0); sa = (struct sockaddr *)&in4; } else if(SCAMPER_ADDR_TYPE_IS_IPV6(addr)) { sockaddr_compose((struct sockaddr *)&in6, AF_INET6, addr->addr, 0); sa = (struct sockaddr *)&in6; } if(sa == NULL) return NULL; sl = sockaddr_len(sa); if(getnameinfo(sa, sl, buf, len, NULL, 0, NI_NAMEREQD) != 0) return NULL; return buf; }
static int rosedb_send_log(int sock, struct sockaddr *dst_addr, knot_pkt_t *pkt, const char *threat_code, struct query_data *qdata) { char buf[SYSLOG_BUFLEN]; char *stream = buf; size_t maxlen = sizeof(buf); time_t now = time(NULL); struct tm tm; localtime_r(&now, &tm); /* Add facility. */ STREAM_WRITE(stream, &maxlen, snprintf, "<%u>", SYSLOG_FACILITY); /* Current local time (4.3.2)*/ STREAM_WRITE(stream, &maxlen, strftime, "%b %d %H:%M:%S ", &tm); /* Host name / Component. */ STREAM_WRITE(stream, &maxlen, snprintf, "%s ", conf()->identity); STREAM_WRITE(stream, &maxlen, snprintf, "%s[%lu]: ", PACKAGE_NAME, (unsigned long) getpid()); /* Prepare log message line. */ int ret = rosedb_log_message(stream, &maxlen, pkt, threat_code, qdata); if (ret != KNOT_EOK) { return ret; } /* Send log message line. */ sendto(sock, buf, sizeof(buf) - maxlen, 0, dst_addr, sockaddr_len(dst_addr)); return ret; }
int main(int argc, char *argv[]) { plan(TESTS_COUNT + 1); mm_ctx_t mm; mm_ctx_mempool(&mm, MM_DEFAULT_BLKSIZE); conf_remote_t remote; memset(&remote, 0, sizeof(conf_remote_t)); sockaddr_set(&remote.addr, AF_INET, "127.0.0.1", 0); sockaddr_set(&remote.via, AF_INET, "127.0.0.1", 0); /* Create fake server environment. */ server_t server; int ret = create_fake_server(&server, &mm); ok(ret == KNOT_EOK, "requestor: initialize fake server"); /* Initialize requestor. */ struct knot_requestor requestor; knot_requestor_init(&requestor, &mm); knot_requestor_overlay(&requestor, &dummy_module, NULL); /* Test requestor in disconnected environment. */ test_disconnected(&requestor, &remote); /* Bind to random port. */ int origin_fd = net_bound_socket(SOCK_STREAM, &remote.addr, 0); assert(origin_fd > 0); socklen_t addr_len = sockaddr_len((struct sockaddr *)&remote.addr); getsockname(origin_fd, (struct sockaddr *)&remote.addr, &addr_len); ret = listen(origin_fd, 10); assert(ret == 0); /* Responder thread. */ pthread_t thread; pthread_create(&thread, 0, responder_thread, &origin_fd); /* Test requestor in connected environment. */ test_connected(&requestor, &remote); /*! \todo #243 TSIG secured requests test should be implemented. */ /* Terminate responder. */ int responder = net_connected_socket(SOCK_STREAM, &remote.addr, NULL, 0); assert(responder > 0); tcp_send_msg(responder, (const uint8_t *)"", 1, NULL); (void) pthread_join(thread, 0); close(responder); /* Close requestor. */ knot_requestor_clear(&requestor); close(origin_fd); /* Cleanup. */ mp_delete((struct mempool *)mm.ctx); server_deinit(&server); conf_free(conf(), false); return 0; }
int socket_bind(int sockfd, struct sockaddr *addr) { socklen_t len; len = sockaddr_len(addr); return bind(sockfd, addr, len); }
static iodev_t * tcp_create(iodev_t *dev, struct sockaddr *local, struct sockaddr *remote, size_t bufsize, int with_linebuf) { // First create the basic (slightly larger) config iodev_cfg_t *cfg = iodev_alloc_cfg(sizeof(tcp_cfg_t), "tcp", tcp_free_cfg); iodev_t *tcp = iodev_init(dev, cfg, bufsize); // Initialise the extras tcp_cfg_t *tcfg = tcp_getcfg(tcp); tcfg->addrlen = local != NULL ? sockaddr_len(local) : remote != NULL ? sockaddr_len(remote) : 0; tcfg->local = sockaddr_dup(local); tcfg->remote = sockaddr_dup(remote); if (with_linebuf) dev->linebuf = stringstore_init(NULL); // default functions tcp->open = tcp_open; tcp->close = tcp_close; tcp->configure = tcp_configure; return tcp; }
int Bind(int sockfd, const struct sockaddr_storage *addr) { socklen_t addrlen = sockaddr_len(addr); int res = bind(sockfd, (struct sockaddr *)addr, addrlen); if (res < 0) { fprintf(stderr, "ERROR: %s() failed (%d) errno(%d) ", __func__, res, errno); perror("- bind"); close(sockfd); exit(EXIT_FAIL_SOCK); } return res; }
/* * scamper_rtsock_getifindex * * figure out the outgoing interface id / route using route sockets * * route(4) gives an overview of the functions called in here */ static int scamper_rtsock_getifindex(int fd, scamper_addr_t *dst) { struct sockaddr_storage sas; struct sockaddr_dl *sdl; struct rt_msghdr *rtm; uint8_t buf[1024]; size_t len; ssize_t ss; int slen; if(SCAMPER_ADDR_TYPE_IS_IPV4(dst)) sockaddr_compose((struct sockaddr *)&sas, AF_INET, dst->addr, 0); else if(SCAMPER_ADDR_TYPE_IS_IPV6(dst)) sockaddr_compose((struct sockaddr *)&sas, AF_INET6, dst->addr, 0); else return -1; if((slen = sockaddr_len((struct sockaddr *)&sas)) <= 0) return -1; len = sizeof(struct rt_msghdr) + scamper_rtsock_roundup(slen) + scamper_rtsock_roundup(sizeof(struct sockaddr_dl)); if(len > sizeof(buf)) return -1; memset(buf, 0, len); rtm = (struct rt_msghdr *)buf; rtm->rtm_msglen = len; rtm->rtm_version = RTM_VERSION; rtm->rtm_type = RTM_GET; rtm->rtm_addrs = RTA_DST | RTA_IFP; rtm->rtm_pid = pid; rtm->rtm_seq = seq; memcpy(buf + sizeof(struct rt_msghdr), &sas, (size_t)slen); sdl = (struct sockaddr_dl *)(buf + sizeof(struct rt_msghdr) + scamper_rtsock_roundup(slen)); sdl->sdl_family = AF_LINK; #if !defined(__sun__) sdl->sdl_len = sizeof(struct sockaddr_dl); #endif if((ss = write(fd, buf, len)) < 0 || (size_t)ss != len) { printerror(errno, strerror, __func__, "could not write routing socket"); return -1; } return 0; }
int main(int argc, char *argv[]) { int sockfd; int pkt_size = 3000; int opt; int addr_family = AF_INET6; /* Default address family */ uint16_t dest_port = PORT; char *dest_ip; int len_send, len_recv; char buf_send[65535], buf_recv[65535]; /* Adding support for both IPv4 and IPv6 */ struct sockaddr_storage dest_addr; /* Can contain both sockaddr_in and sockaddr_in6 */ memset(&dest_addr, 0, sizeof(dest_addr)); while ((opt = getopt(argc, argv, "s:64v:p:")) != -1) { if (opt == 's') pkt_size = atoi(optarg); if (opt == '4') addr_family = AF_INET; if (opt == '6') addr_family = AF_INET6; if (opt == 'v') verbose = atoi(optarg); if (opt == 'p') dest_port = atoi(optarg); } if (optind >= argc) { fprintf(stderr, "Expected dest IP-address (IPv6 or IPv4) argument after options\n"); exit(2); } dest_ip = argv[optind]; if (verbose > 0) printf("Destination IP:%s port:%d\n", dest_ip, dest_port); sockfd = socket(addr_family, SOCK_DGRAM, 0); /* Socket options, see man-pages ip(7) and ipv6(7) */ //int set_pmtu_disc = IP_PMTUDISC_DO; /* do PMTU = Don't Fragment */ int set_pmtu_disc = IP_PMTUDISC_DONT; /* Allow fragments, dont do PMTU */ Setsockopt(sockfd, IPPROTO_IP, IP_MTU_DISCOVER, &set_pmtu_disc, sizeof(int)); Setsockopt(sockfd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &set_pmtu_disc, sizeof(int)); /* Setup dest_addr depending on IPv4 or IPv6 address */ setup_sockaddr(addr_family, &dest_addr, dest_ip, dest_port); /* Connect to recv ICMP error messages */ connect(sockfd, (struct sockaddr *)&dest_addr, sockaddr_len(&dest_addr)); len_send = send_packet(sockfd, &dest_addr, buf_send, pkt_size); len_recv = recv_packet(sockfd, &dest_addr, buf_recv, len_send); validate_packet(len_send, len_recv, buf_send, buf_recv); }
int send_packet(int sockfd, const struct sockaddr_storage *dest_addr, char *buf_send, uint16_t pkt_size) { socklen_t len_addr = sockaddr_len(dest_addr); int len_send; /* -- Send packet -- */ len_send = sendto(sockfd, buf_send, pkt_size, 0, (const struct sockaddr*) dest_addr, len_addr); if (len_send < 0) { fprintf(stderr, "ERROR: %s() sendto failed (%d) ", __func__, len_send); perror("- sendto"); exit(5); } if (verbose > 1) { printf("Send UDP packet of length:%d\n", len_send); } return len_send; }
static struct sockaddr *copy_sockaddr(struct sockaddr_storage *ss, socklen_t len, struct error *err) { size_t expected_len = sockaddr_len((struct sockaddr *)ss, err); if (expected_len) { if (len == expected_len) { struct sockaddr *sa = xalloc(expected_len); memcpy(sa, ss, expected_len); return sa; } error_set(err, ERROR_INVALID, "strange socket address length for family %d" " (%u bytes)", (int)ss->ss_family, (unsigned int)len); } return NULL; }
static struct socket *connect_addresses(struct socket_factory *gf, struct sockaddr **addrs, struct error *err) { struct sockaddr *addr; struct addrinfo *ai; struct addrinfo *addrinfos; struct addrinfo **next = &addrinfos; assert(gf->ops == &simple_socket_factory_ops); while ((addr = *addrs++)) { ai = xalloc(sizeof *ai); ai->ai_next = NULL; ai->ai_family = addr->sa_family; ai->ai_socktype = SOCK_STREAM; ai->ai_protocol = 0; ai->ai_addr = NULL; ai->ai_addrlen = sockaddr_len(addr, err); *next = ai; next = &ai->ai_next; if (!ai->ai_addrlen) goto error; ai->ai_addr = xalloc(ai->ai_addrlen); memcpy(ai->ai_addr, addr, ai->ai_addrlen); } if (addrinfos) return &client_socket_create(addrinfos, our_freeaddrinfo)->base.base; error_set(err, ERROR_INVALID, "no addresses to connect to"); return NULL; error: our_freeaddrinfo(addrinfos); return NULL; }
int recv_packet(int sockfd, const struct sockaddr_storage *dest_addr, char *buf_recv, uint16_t pkt_size) { /* Notes: dest_addr will be used for validating against from_addr */ socklen_t len_addr = sockaddr_len(dest_addr); // struct sockaddr *from_addr; int len_recv; /* -- Receive packet -- */ if (verbose > 1) { printf("Waiting for recvfrom()\n"); } len_recv = recvfrom(sockfd, buf_recv, pkt_size, 0, NULL, NULL); if (len_recv < 0) { perror("recvfrom"); exit(5); } if (verbose > 1) { printf("Received UDP packet of length:%d\n", len_recv); } return len_recv; }
int /* O - 0 on success, -1 on error */ _cups_getifaddrs(struct ifaddrs **addrs)/* O - List of interfaces */ { int sock; /* Socket */ char buffer[65536], /* Buffer for address info */ *bufptr, /* Pointer into buffer */ *bufend; /* End of buffer */ struct ifconf conf; /* Interface configurations */ struct sockaddr addr; /* Address data */ struct ifreq *ifp; /* Interface data */ int ifpsize; /* Size of interface data */ struct ifaddrs *temp; /* Pointer to current interface */ struct ifreq request; /* Interface request */ /* * Start with an empty list... */ if (addrs == NULL) return (-1); *addrs = NULL; /* * Create a UDP socket to get the interface data... */ memset (&addr, 0, sizeof(addr)); if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) return (-1); /* * Try to get the list of interfaces... */ conf.ifc_len = sizeof(buffer); conf.ifc_buf = buffer; if (ioctl(sock, SIOCGIFCONF, &conf) < 0) { /* * Couldn't get the list of interfaces... */ close(sock); return (-1); } /* * OK, got the list of interfaces, now lets step through the * buffer to pull them out... */ # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN # define sockaddr_len(a) ((a)->sa_len) # else # define sockaddr_len(a) (sizeof(struct sockaddr)) # endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ for (bufptr = buffer, bufend = buffer + conf.ifc_len; bufptr < bufend; bufptr += ifpsize) { /* * Get the current interface information... */ ifp = (struct ifreq *)bufptr; ifpsize = sizeof(ifp->ifr_name) + sockaddr_len(&(ifp->ifr_addr)); if (ifpsize < sizeof(struct ifreq)) ifpsize = sizeof(struct ifreq); memset(&request, 0, sizeof(request)); memcpy(request.ifr_name, ifp->ifr_name, sizeof(ifp->ifr_name)); /* * Check the status of the interface... */ if (ioctl(sock, SIOCGIFFLAGS, &request) < 0) continue; /* * Allocate memory for a single interface record... */ if ((temp = calloc(1, sizeof(struct ifaddrs))) == NULL) { /* * Unable to allocate memory... */ close(sock); return (-1); } /* * Add this record to the front of the list and copy the name, flags, * and network address... */ temp->ifa_next = *addrs; *addrs = temp; temp->ifa_name = strdup(ifp->ifr_name); temp->ifa_flags = request.ifr_flags; if ((temp->ifa_addr = calloc(1, sockaddr_len(&(ifp->ifr_addr)))) != NULL) memcpy(temp->ifa_addr, &(ifp->ifr_addr), sockaddr_len(&(ifp->ifr_addr))); /* * Try to get the netmask for the interface... */ if (!ioctl(sock, SIOCGIFNETMASK, &request)) { /* * Got it, make a copy... */ if ((temp->ifa_netmask = calloc(1, sizeof(request.ifr_netmask))) != NULL) memcpy(temp->ifa_netmask, &(request.ifr_netmask), sizeof(request.ifr_netmask)); } /* * Then get the broadcast or point-to-point (destination) address, * if applicable... */ if (temp->ifa_flags & IFF_BROADCAST) { /* * Have a broadcast address, so get it! */ if (!ioctl(sock, SIOCGIFBRDADDR, &request)) { /* * Got it, make a copy... */ if ((temp->ifa_broadaddr = calloc(1, sizeof(request.ifr_broadaddr))) != NULL) memcpy(temp->ifa_broadaddr, &(request.ifr_broadaddr), sizeof(request.ifr_broadaddr)); } } else if (temp->ifa_flags & IFF_POINTOPOINT) { /* * Point-to-point interface; grab the remote address... */ if (!ioctl(sock, SIOCGIFDSTADDR, &request)) { temp->ifa_dstaddr = malloc(sizeof(request.ifr_dstaddr)); memcpy(temp->ifa_dstaddr, &(request.ifr_dstaddr), sizeof(request.ifr_dstaddr)); } } } /* * OK, we're done with the socket, close it and return 0... */ close(sock); return (0); }
static void rtsock_parsemsg(uint8_t *buf, size_t len) { struct rt_msghdr *rtm; struct sockaddr *addrs[RTAX_MAX]; struct sockaddr_dl *sdl; struct sockaddr *sa; struct in6_addr *ip6; size_t off, tmp, x; int i, ifindex; void *addr; scamper_addr_t *gw; rtsock_pair_t *pair; scamper_route_t *route; x = 0; while(x < len) { if(len - x < sizeof(struct rt_msghdr)) { scamper_debug(__func__,"len %d != %d",len,sizeof(struct rt_msghdr)); return; } /* * check if the message is something we want, and that we have * a pair for it */ rtm = (struct rt_msghdr *)(buf + x); if(rtm->rtm_pid != pid || rtm->rtm_msglen > len - x || rtm->rtm_type != RTM_GET || (rtm->rtm_flags & RTF_DONE) == 0 || (pair = rtsock_pair_get(rtm->rtm_seq)) == NULL) { x += rtm->rtm_msglen; continue; } route = pair->route; rtsock_pair_free(pair); ifindex = -1; addr = NULL; gw = NULL; if(rtm->rtm_errno != 0) { route->error = rtm->rtm_errno; goto done; } off = sizeof(struct rt_msghdr); memset(addrs, 0, sizeof(addrs)); for(i=0; i<RTAX_MAX; i++) { if(rtm->rtm_addrs & (1 << i)) { addrs[i] = sa = (struct sockaddr *)(buf + x + off); if((tmp = sockaddr_len(sa)) == -1) { printerror(0,NULL,__func__,"unhandled af %d",sa->sa_family); route->error = EINVAL; goto done; } off += scamper_rtsock_roundup(tmp); } } if((sdl = (struct sockaddr_dl *)addrs[RTAX_IFP]) != NULL) { if(sdl->sdl_family != AF_LINK) { printerror(0, NULL, __func__, "sdl_family %d", sdl->sdl_family); route->error = EINVAL; goto done; } ifindex = sdl->sdl_index; } if((sa = addrs[RTAX_GATEWAY]) != NULL) { if(sa->sa_family == AF_INET) { i = SCAMPER_ADDR_TYPE_IPV4; addr = &((struct sockaddr_in *)sa)->sin_addr; } else if(sa->sa_family == AF_INET6) { /* * check to see if the gw address is a link local address. if * it is, then drop the embedded index from the gateway address */ ip6 = &((struct sockaddr_in6 *)sa)->sin6_addr; if(IN6_IS_ADDR_LINKLOCAL(ip6)) { ip6->s6_addr[2] = 0; ip6->s6_addr[3] = 0; } i = SCAMPER_ADDR_TYPE_IPV6; addr = ip6; } else if(sa->sa_family == AF_LINK) { sdl = (struct sockaddr_dl *)sa; if(sdl->sdl_type == IFT_ETHER && sdl->sdl_alen == ETHER_ADDR_LEN) { i = SCAMPER_ADDR_TYPE_ETHERNET; addr = sdl->sdl_data + sdl->sdl_nlen; } } /* * if we have got a gateway address that we know what to do with, * then store it here. */ if(addr != NULL && (gw = scamper_addrcache_get(addrcache, i, addr)) == NULL) { scamper_debug(__func__, "could not get rtsmsg->rr.gw"); route->error = EINVAL; goto done; } } done: route->gw = gw; route->ifindex = ifindex; route->cb(route); x += rtm->rtm_msglen; } return; }
static int rosedb_log_message(char *stream, size_t *maxlen, knot_pkt_t *pkt, const char *threat_code, struct query_data *qdata) { char dname_buf[KNOT_DNAME_MAXLEN] = {'\0'}; struct sockaddr_storage addr; socklen_t addr_len = sizeof(addr); time_t now = time(NULL); struct tm tm; gmtime_r(&now, &tm); /* Field 1 Timestamp (UTC). */ STREAM_WRITE(stream, maxlen, strftime, "%Y-%m-%d %H:%M:%S\t", &tm); /* Field 2/3 Remote, local address. */ const struct sockaddr *remote = (const struct sockaddr *)qdata->param->remote; memcpy(&addr, remote, sockaddr_len(remote)); int client_port = sockaddr_port(&addr); sockaddr_port_set(&addr, 0); STREAM_WRITE(stream, maxlen, sockaddr_tostr, &addr); STREAM_WRITE(stream, maxlen, snprintf, "\t"); getsockname(qdata->param->socket, (struct sockaddr *)&addr, &addr_len); int server_port = sockaddr_port(&addr); sockaddr_port_set(&addr, 0); STREAM_WRITE(stream, maxlen, sockaddr_tostr, &addr); STREAM_WRITE(stream, maxlen, snprintf, "\t"); /* Field 4/5 Local, remote port. */ STREAM_WRITE(stream, maxlen, snprintf, "%d\t%d\t", client_port, server_port); /* Field 6 Threat ID. */ STREAM_WRITE(stream, maxlen, snprintf, "%s\t", threat_code); /* Field 7 - 13 NULL */ STREAM_WRITE(stream, maxlen, snprintf, "\t\t\t\t\t\t\t"); /* Field 14 QNAME */ knot_dname_to_str(dname_buf, knot_pkt_qname(qdata->query), sizeof(dname_buf)); STREAM_WRITE(stream, maxlen, snprintf, "%s\t", dname_buf); /* Field 15 Resolution (0 = local, 1 = lookup)*/ STREAM_WRITE(stream, maxlen, snprintf, "0\t"); /* Field 16 RDATA. * - Return randomly RDATA in the answer section (probabilistic rotation). * - Empty if no answer. */ const knot_pktsection_t *ans = knot_pkt_section(pkt, KNOT_ANSWER); if (ans->count > 0) { const knot_rrset_t *rr = &ans->rr[knot_random_uint16_t() % ans->count]; int ret = knot_rrset_txt_dump_data(rr, 0, stream, *maxlen, &KNOT_DUMP_STYLE_DEFAULT); if (ret < 0) { return ret; } stream_skip(&stream, maxlen, ret); } STREAM_WRITE(stream, maxlen, snprintf, "\t"); /* Field 17 Connection type. */ STREAM_WRITE(stream, maxlen, snprintf, "%s\t", net_is_connected(qdata->param->socket) ? "TCP" : "UDP"); /* Field 18 Query type. */ char type_str[16] = { '\0' }; knot_rrtype_to_string(knot_pkt_qtype(qdata->query), type_str, sizeof(type_str)); STREAM_WRITE(stream, maxlen, snprintf, "%s\t", type_str); /* Field 19 First authority. */ const knot_pktsection_t *ns = knot_pkt_section(pkt, KNOT_AUTHORITY); if (ns->count > 0 && ns->rr[0].type == KNOT_RRTYPE_NS) { const knot_dname_t *label = knot_ns_name(&ns->rr[0].rrs, 0); memset(dname_buf, 0, sizeof(dname_buf)); memcpy(dname_buf, label + 1, *label); STREAM_WRITE(stream, maxlen, snprintf, "%s", dname_buf); } return KNOT_EOK; }
static int pfkey_send(int sd, uint8_t satype, uint8_t mtype, uint8_t dir, int af, union ldpd_addr *src, union ldpd_addr *dst, uint32_t spi, uint8_t aalg, int alen, char *akey, uint8_t ealg, int elen, char *ekey, uint16_t sport, uint16_t dport) { struct sadb_msg smsg; struct sadb_sa sa; struct sadb_address sa_src, sa_dst; struct sadb_key sa_akey, sa_ekey; struct sadb_spirange sa_spirange; struct iovec iov[IOV_CNT]; ssize_t n; int len = 0; int iov_cnt; struct sockaddr_storage smask, dmask; union sockunion su_src, su_dst; if (!pid) pid = getpid(); /* we need clean sockaddr... no ports set */ memset(&smask, 0, sizeof(smask)); addr2sa(af, src, 0, &su_src); switch (af) { case AF_INET: memset(&((struct sockaddr_in *)&smask)->sin_addr, 0xff, 32/8); break; case AF_INET6: memset(&((struct sockaddr_in6 *)&smask)->sin6_addr, 0xff, 128/8); break; default: return (-1); } smask.ss_family = su_src.sa.sa_family; smask.ss_len = sockaddr_len(&su_src.sa); memset(&dmask, 0, sizeof(dmask)); addr2sa(af, dst, 0, &su_dst); switch (af) { case AF_INET: memset(&((struct sockaddr_in *)&dmask)->sin_addr, 0xff, 32/8); break; case AF_INET6: memset(&((struct sockaddr_in6 *)&dmask)->sin6_addr, 0xff, 128/8); break; default: return (-1); } dmask.ss_family = su_dst.sa.sa_family; dmask.ss_len = sockaddr_len(&su_dst.sa); memset(&smsg, 0, sizeof(smsg)); smsg.sadb_msg_version = PF_KEY_V2; smsg.sadb_msg_seq = ++sadb_msg_seq; smsg.sadb_msg_pid = pid; smsg.sadb_msg_len = sizeof(smsg) / 8; smsg.sadb_msg_type = mtype; smsg.sadb_msg_satype = satype; switch (mtype) { case SADB_GETSPI: memset(&sa_spirange, 0, sizeof(sa_spirange)); sa_spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE; sa_spirange.sadb_spirange_len = sizeof(sa_spirange) / 8; sa_spirange.sadb_spirange_min = 0x100; sa_spirange.sadb_spirange_max = 0xffffffff; sa_spirange.sadb_spirange_reserved = 0; break; case SADB_ADD: case SADB_UPDATE: case SADB_DELETE: memset(&sa, 0, sizeof(sa)); sa.sadb_sa_exttype = SADB_EXT_SA; sa.sadb_sa_len = sizeof(sa) / 8; sa.sadb_sa_replay = 0; sa.sadb_sa_spi = htonl(spi); sa.sadb_sa_state = SADB_SASTATE_MATURE; break; } memset(&sa_src, 0, sizeof(sa_src)); sa_src.sadb_address_exttype = SADB_EXT_ADDRESS_SRC; sa_src.sadb_address_len = (sizeof(sa_src) + ROUNDUP(sockaddr_len(&su_src.sa))) / 8; memset(&sa_dst, 0, sizeof(sa_dst)); sa_dst.sadb_address_exttype = SADB_EXT_ADDRESS_DST; sa_dst.sadb_address_len = (sizeof(sa_dst) + ROUNDUP(sockaddr_len(&su_dst.sa))) / 8; sa.sadb_sa_auth = aalg; sa.sadb_sa_encrypt = SADB_X_EALG_AES; /* XXX */ switch (mtype) { case SADB_ADD: case SADB_UPDATE: memset(&sa_akey, 0, sizeof(sa_akey)); sa_akey.sadb_key_exttype = SADB_EXT_KEY_AUTH; sa_akey.sadb_key_len = (sizeof(sa_akey) + ((alen + 7) / 8) * 8) / 8; sa_akey.sadb_key_bits = 8 * alen; memset(&sa_ekey, 0, sizeof(sa_ekey)); sa_ekey.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT; sa_ekey.sadb_key_len = (sizeof(sa_ekey) + ((elen + 7) / 8) * 8) / 8; sa_ekey.sadb_key_bits = 8 * elen; break; } iov_cnt = 0; /* msghdr */ iov[iov_cnt].iov_base = &smsg; iov[iov_cnt].iov_len = sizeof(smsg); iov_cnt++; switch (mtype) { case SADB_ADD: case SADB_UPDATE: case SADB_DELETE: /* SA hdr */ iov[iov_cnt].iov_base = &sa; iov[iov_cnt].iov_len = sizeof(sa); smsg.sadb_msg_len += sa.sadb_sa_len; iov_cnt++; break; case SADB_GETSPI: /* SPI range */ iov[iov_cnt].iov_base = &sa_spirange; iov[iov_cnt].iov_len = sizeof(sa_spirange); smsg.sadb_msg_len += sa_spirange.sadb_spirange_len; iov_cnt++; break; } /* dest addr */ iov[iov_cnt].iov_base = &sa_dst; iov[iov_cnt].iov_len = sizeof(sa_dst); iov_cnt++; iov[iov_cnt].iov_base = &su_dst; iov[iov_cnt].iov_len = ROUNDUP(sockaddr_len(&su_dst.sa)); smsg.sadb_msg_len += sa_dst.sadb_address_len; iov_cnt++; /* src addr */ iov[iov_cnt].iov_base = &sa_src; iov[iov_cnt].iov_len = sizeof(sa_src); iov_cnt++; iov[iov_cnt].iov_base = &su_src; iov[iov_cnt].iov_len = ROUNDUP(sockaddr_len(&su_src.sa)); smsg.sadb_msg_len += sa_src.sadb_address_len; iov_cnt++; switch (mtype) { case SADB_ADD: case SADB_UPDATE: if (alen) { /* auth key */ iov[iov_cnt].iov_base = &sa_akey; iov[iov_cnt].iov_len = sizeof(sa_akey); iov_cnt++; iov[iov_cnt].iov_base = akey; iov[iov_cnt].iov_len = ((alen + 7) / 8) * 8; smsg.sadb_msg_len += sa_akey.sadb_key_len; iov_cnt++; } if (elen) { /* encryption key */ iov[iov_cnt].iov_base = &sa_ekey; iov[iov_cnt].iov_len = sizeof(sa_ekey); iov_cnt++; iov[iov_cnt].iov_base = ekey; iov[iov_cnt].iov_len = ((elen + 7) / 8) * 8; smsg.sadb_msg_len += sa_ekey.sadb_key_len; iov_cnt++; } break; } len = smsg.sadb_msg_len * 8; do { n = writev(sd, iov, iov_cnt); } while (n == -1 && (errno == EAGAIN || errno == EINTR)); if (n == -1) { log_warn("writev (%d/%d)", iov_cnt, len); return (-1); } return (0); }
ssize_t socket_sendto(int sockfd, const char* buf, int start, int end, int flags, struct sockaddr *dest_addr) { return sendto(sockfd, buf + start, end - start, flags, dest_addr, sockaddr_len(dest_addr)); }