static int ssdp_ip4_msearch(interface *i,const uint32_t *saddr) { const unsigned char hw[ETH_ALEN] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0xc }; uint32_t net = htonl(SSDP_NET4); struct tpacket_hdr *thdr; struct udphdr *udp; struct iphdr *ip; size_t flen,tlen; void *frame; int r; if((frame = get_tx_frame(i,&flen)) == NULL) { return -1; } thdr = frame; tlen = thdr->tp_mac; if((r = prep_eth_header((char *)frame + tlen,flen - tlen,i, hw,ETH_P_IP)) < 0) { abort_tx_frame(i,frame); return -1; } tlen += r; ip = (struct iphdr *)((char *)frame + tlen); if((r = prep_ipv4_header(ip,flen - tlen,*saddr,net,IPPROTO_UDP)) < 0) { abort_tx_frame(i,frame); return -1; } tlen += r; if(flen - tlen < sizeof(*udp)) { abort_tx_frame(i,frame); return -1; } udp = (struct udphdr *)((char *)frame + tlen); udp->source = htons(SSDP_UDP_PORT); udp->dest = htons(SSDP_UDP_PORT); tlen += sizeof(*udp); r = setup_ssdp_query((char *)frame + tlen,flen - tlen); if(r < 0) { abort_tx_frame(i,frame); return -1; } tlen += r; ip->tot_len = htons(tlen - ((const char *)ip - (const char *)frame)); ip->check = ipv4_csum(ip); udp->len = htons(ntohs(ip->tot_len) - ip->ihl * 4u); udp->check = udp4_csum(ip); thdr->tp_len = tlen - thdr->tp_mac; return send_tx_frame(i,frame); }
// Always goes to ff02::2 (ALL-HOSTS), from each source address. int tx_ipv4_bcast_pings(interface *i,const uint32_t *saddr){ struct tpacket_hdr *thdr; struct icmphdr *icmp; struct iphdr *ip; size_t flen,tlen; void *frame; int r; if((frame = get_tx_frame(i,&flen)) == NULL){ return -1; } thdr = frame; tlen = thdr->tp_mac; if((r = prep_eth_bcast((char *)frame + tlen,flen - tlen,i,ETH_P_IP)) < 0){ abort_tx_frame(i,frame); return -1; } tlen += r; ip = (struct iphdr *)((char *)frame + tlen); // FIXME get bcast address appropriate for route if((r = prep_ipv4_bcast(ip,flen - tlen,*saddr,IPPROTO_ICMP)) < 0){ abort_tx_frame(i,frame); return -1; } tlen += r; if(flen - tlen < sizeof(*icmp) + PING4_PAYLOAD_LEN){ abort_tx_frame(i,frame); return -1; } icmp = (struct icmphdr *)((char *)frame + tlen); icmp->type = ICMP_ECHO; icmp->code = 0; tlen += sizeof(*icmp) + PING4_PAYLOAD_LEN; thdr->tp_len = tlen; ip->tot_len = htons((const char *)icmp - (const char *)ip + sizeof(*icmp) + PING4_PAYLOAD_LEN); icmp->checksum = 0; icmp->checksum = icmp4_csum(icmp,sizeof(*icmp)); ip->check = ipv4_csum(ip); return send_tx_frame(i,frame); }