void tun_serv_in(int fd_udp, int fd_tun, struct tun_state *state, char *buf) { int recvd=xread(fd_tun, buf, BUFF_SIZE); debug_print("serv: recvd %dB from tun\n", recvd); if (recvd > MIN_PKT_SIZE) { /* Remove PlanetLab TUN PPI header */ if (state->planetlab) { buf+=4;recvd-=4; } struct tun_rec *rec = NULL; /* read sport for clients mapping */ int sport = (int) ntohs( *((uint16_t *)(buf+22)) ); if ( (rec = g_hash_table_lookup(state->serv, &sport)) ) { int sent = xsendto(fd_udp, rec->sa, buf, recvd); debug_print("serv: wrote %dB to udp\n",sent); } else { errno=EFAULT; die("lookup"); } } }
/** * Broadcast an ARP packet. */ static void arp(int op, const struct ether_addr *source_eth, struct in_addr source_ip, const struct ether_addr *target_eth, struct in_addr target_ip) { struct arp_packet p; memset(&p, 0, sizeof(p)); // ether header p.eth.ether_type = htons(ETHERTYPE_ARP); memcpy(p.eth.ether_shost, source_eth, ETH_ALEN); memset(p.eth.ether_dhost, 0xff, ETH_ALEN); // arp request p.arp.arp_hrd = htons(ARPHRD_ETHER); p.arp.arp_pro = htons(ETHERTYPE_IP); p.arp.arp_hln = ETH_ALEN; p.arp.arp_pln = 4; p.arp.arp_op = htons(op); memcpy(&p.arp.arp_sha, source_eth, ETH_ALEN); memcpy(&p.arp.arp_spa, &source_ip, sizeof(p.arp.arp_spa)); memcpy(&p.arp.arp_tha, target_eth, ETH_ALEN); memcpy(&p.arp.arp_tpa, &target_ip, sizeof(p.arp.arp_tpa)); // send it xsendto(sock_fd, &p, sizeof(p), &saddr, sizeof(saddr)); // Currently all callers ignore errors, that's why returns are // commented out... //return 0; }
int FAST_FUNC rtnl_send(struct rtnl_handle *rth, char *buf, int len) { struct sockaddr_nl nladdr; memset(&nladdr, 0, sizeof(nladdr)); nladdr.nl_family = AF_NETLINK; return xsendto(rth->fd, buf, len, (struct sockaddr*)&nladdr, sizeof(nladdr)); }
static void ping6(len_and_sockaddr *lsa) { struct icmp6_hdr *pkt; int c; int sockopt; pkt = (struct icmp6_hdr *) G.packet; /*memset(pkt, 0, sizeof(G.packet)); already is */ pkt->icmp6_type = ICMP6_ECHO_REQUEST; pkt->icmp6_id = G.myid; sockopt = offsetof(struct icmp6_hdr, icmp6_cksum); setsockopt_int(pingsock, SOL_RAW, IPV6_CHECKSUM, sockopt); xsendto(pingsock, G.packet, DEFDATALEN + sizeof(struct icmp6_hdr), &lsa->u.sa, lsa->len); /* listen for replies */ while (1) { #if 0 struct sockaddr_in6 from; socklen_t fromlen = sizeof(from); c = recvfrom(pingsock, G.packet, sizeof(G.packet), 0, (struct sockaddr *) &from, &fromlen); #else c = recv(pingsock, G.packet, sizeof(G.packet), 0); #endif if (c < 0) { if (errno != EINTR) bb_perror_msg("recvfrom"); continue; } if (c >= ICMP_MINLEN) { /* icmp6_hdr */ if (pkt->icmp6_id != G.myid) continue; /* not our ping */ if (pkt->icmp6_type == ICMP6_ECHO_REPLY) break; } } if (ENABLE_FEATURE_CLEAN_UP) close(pingsock); }
static void ping4(len_and_sockaddr *lsa) { struct icmp *pkt; int c; pkt = (struct icmp *) G.packet; /*memset(pkt, 0, sizeof(G.packet)); already is */ pkt->icmp_type = ICMP_ECHO; pkt->icmp_id = G.myid; pkt->icmp_cksum = inet_cksum((uint16_t *) pkt, sizeof(G.packet)); xsendto(pingsock, G.packet, DEFDATALEN + ICMP_MINLEN, &lsa->u.sa, lsa->len); /* listen for replies */ while (1) { #if 0 struct sockaddr_in from; socklen_t fromlen = sizeof(from); c = recvfrom(pingsock, G.packet, sizeof(G.packet), 0, (struct sockaddr *) &from, &fromlen); #else c = recv(pingsock, G.packet, sizeof(G.packet), 0); #endif if (c < 0) { if (errno != EINTR) bb_perror_msg("recvfrom"); continue; } if (c >= 76) { /* ip + icmp */ struct iphdr *iphdr = (struct iphdr *) G.packet; pkt = (struct icmp *) (G.packet + (iphdr->ihl << 2)); /* skip ip hdr */ if (pkt->icmp_id != G.myid) continue; /* not our ping */ if (pkt->icmp_type == ICMP_ECHOREPLY) break; } } if (ENABLE_FEATURE_CLEAN_UP) close(pingsock); }
int FAST_FUNC xrtnl_wilddump_request(struct rtnl_handle *rth, int family, int type) { struct { struct nlmsghdr nlh; struct rtgenmsg g; } req; struct sockaddr_nl nladdr; memset(&nladdr, 0, sizeof(nladdr)); nladdr.nl_family = AF_NETLINK; req.nlh.nlmsg_len = sizeof(req); req.nlh.nlmsg_type = type; req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST; req.nlh.nlmsg_pid = 0; req.nlh.nlmsg_seq = rth->dump = ++rth->seq; req.g.rtgen_family = family; return xsendto(rth->fd, (void*)&req, sizeof(req), (struct sockaddr*)&nladdr, sizeof(nladdr)); }
/** * Broadcast an ARP packet. */ static void arp( /* int op, - always ARPOP_REQUEST */ /* const struct ether_addr *source_eth, - always ð_addr */ struct in_addr source_ip, const struct ether_addr *target_eth, struct in_addr target_ip) { enum { op = ARPOP_REQUEST }; #define source_eth (ð_addr) struct arp_packet p; memset(&p, 0, sizeof(p)); // ether header p.eth.ether_type = htons(ETHERTYPE_ARP); memcpy(p.eth.ether_shost, source_eth, ETH_ALEN); memset(p.eth.ether_dhost, 0xff, ETH_ALEN); // arp request p.arp.arp_hrd = htons(ARPHRD_ETHER); p.arp.arp_pro = htons(ETHERTYPE_IP); p.arp.arp_hln = ETH_ALEN; p.arp.arp_pln = 4; p.arp.arp_op = htons(op); memcpy(&p.arp.arp_sha, source_eth, ETH_ALEN); memcpy(&p.arp.arp_spa, &source_ip, sizeof(p.arp.arp_spa)); memcpy(&p.arp.arp_tha, target_eth, ETH_ALEN); memcpy(&p.arp.arp_tpa, &target_ip, sizeof(p.arp.arp_tpa)); // send it // Even though sock_fd is already bound to saddr, just send() // won't work, because "socket is not connected" // (and connect() won't fix that, "operation not supported"). // Thus we sendto() to saddr. I wonder which sockaddr // (from bind() or from sendto()?) kernel actually uses // to determine iface to emit the packet from... xsendto(sock_fd, &p, sizeof(p), &saddr, sizeof(saddr)); #undef source_eth }
int ether_wake_main(int argc UNUSED_PARAM, char **argv) { const char *ifname = "eth0"; char *pass; unsigned flags; unsigned char wol_passwd[6]; int wol_passwd_sz = 0; int s; /* Raw socket */ int pktsize; unsigned char outpack[1000]; struct ether_addr eaddr; struct whereto_t whereto; /* who to wake up */ /* handle misc user options */ opt_complementary = "=1"; flags = getopt32(argv, "bi:p:", &ifname, &pass); if (flags & 4) /* -p */ wol_passwd_sz = get_wol_pw(pass, wol_passwd); flags &= 1; /* we further interested only in -b [bcast] flag */ /* create the raw socket */ s = make_socket(); /* now that we have a raw socket we can drop root */ /* xsetuid(getuid()); - but save on code size... */ /* look up the dest mac address */ get_dest_addr(argv[optind], &eaddr); /* fill out the header of the packet */ pktsize = get_fill(outpack, &eaddr, flags /* & 1 OPT_BROADCAST */); bb_debug_dump_packet(outpack, pktsize); /* Fill in the source address, if possible. */ #ifdef __linux__ { struct ifreq if_hwaddr; strncpy_IFNAMSIZ(if_hwaddr.ifr_name, ifname); ioctl_or_perror_and_die(s, SIOCGIFHWADDR, &if_hwaddr, "SIOCGIFHWADDR on %s failed", ifname); memcpy(outpack+6, if_hwaddr.ifr_hwaddr.sa_data, 6); # ifdef DEBUG { unsigned char *hwaddr = if_hwaddr.ifr_hwaddr.sa_data; printf("The hardware address (SIOCGIFHWADDR) of %s is type %d " "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n\n", ifname, if_hwaddr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]); } # endif } #endif /* __linux__ */ bb_debug_dump_packet(outpack, pktsize); /* append the password if specified */ if (wol_passwd_sz > 0) { memcpy(outpack+pktsize, wol_passwd, wol_passwd_sz); pktsize += wol_passwd_sz; } bb_debug_dump_packet(outpack, pktsize); /* This is necessary for broadcasts to work */ if (flags /* & 1 OPT_BROADCAST */) { if (setsockopt_broadcast(s) != 0) bb_perror_msg("SO_BROADCAST"); } #if defined(PF_PACKET) { struct ifreq ifr; strncpy_IFNAMSIZ(ifr.ifr_name, ifname); xioctl(s, SIOCGIFINDEX, &ifr); memset(&whereto, 0, sizeof(whereto)); whereto.sll_family = AF_PACKET; whereto.sll_ifindex = ifr.ifr_ifindex; /* The manual page incorrectly claims the address must be filled. We do so because the code may change to match the docs. */ whereto.sll_halen = ETH_ALEN; memcpy(whereto.sll_addr, outpack, ETH_ALEN); } #else whereto.sa_family = 0; strcpy(whereto.sa_data, ifname); #endif xsendto(s, outpack, pktsize, (struct sockaddr *)&whereto, sizeof(whereto)); if (ENABLE_FEATURE_CLEAN_UP) close(s); return EXIT_SUCCESS; }
static void send_probe(int seq, int ttl) { int len, res; void *out; /* Payload */ #if ENABLE_TRACEROUTE6 if (dest_lsa->u.sa.sa_family == AF_INET6) { struct outdata6_t *pkt = (struct outdata6_t *) outip; pkt->ident6 = htonl(ident); pkt->seq6 = htonl(seq); /*gettimeofday(&pkt->tv, &tz);*/ } else #endif { outdata->seq = seq; outdata->ttl = ttl; // UNUSED: was storing gettimeofday's result there, but never ever checked it /*memcpy(&outdata->tv, tp, sizeof(outdata->tv));*/ if (option_mask32 & OPT_USE_ICMP) { outicmp->icmp_seq = htons(seq); /* Always calculate checksum for icmp packets */ outicmp->icmp_cksum = 0; outicmp->icmp_cksum = inet_cksum((uint16_t *)outicmp, packlen - (sizeof(*outip) + optlen)); if (outicmp->icmp_cksum == 0) outicmp->icmp_cksum = 0xffff; } } //BUG! verbose is (x & OPT_VERBOSE), not a counter! #if 0 //ENABLE_FEATURE_TRACEROUTE_VERBOSE /* XXX undocumented debugging hack */ if (verbose > 1) { const uint16_t *sp; int nshorts, i; sp = (uint16_t *)outip; nshorts = (unsigned)packlen / sizeof(uint16_t); i = 0; printf("[ %d bytes", packlen); while (--nshorts >= 0) { if ((i++ % 8) == 0) printf("\n\t"); printf(" %04x", ntohs(*sp)); sp++; } if (packlen & 1) { if ((i % 8) == 0) printf("\n\t"); printf(" %02x", *(unsigned char *)sp); } printf("]\n"); } #endif #if ENABLE_TRACEROUTE6 if (dest_lsa->u.sa.sa_family == AF_INET6) { res = setsockopt(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)); if (res < 0) bb_perror_msg_and_die("setsockopt UNICAST_HOPS %d", ttl); out = outip; len = packlen; } else #endif { #if defined IP_TTL res = setsockopt(sndsock, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)); if (res < 0) bb_perror_msg_and_die("setsockopt ttl %d", ttl); #endif out = outicmp; len = packlen - sizeof(*outip); if (!(option_mask32 & OPT_USE_ICMP)) { out = outdata; len -= sizeof(*outudp); set_nport(&dest_lsa->u.sa, htons(port + seq)); } } res = xsendto(sndsock, out, len, &dest_lsa->u.sa, dest_lsa->len); if (res != len) bb_info_msg("sent %d octets, ret=%d", len, res); }