/* * sends an IP packet, if it's alredy constructed */ static ssize_t _sendip(struct iodesc * d, struct ip * ip, size_t len) { u_char *ea; if (ip->ip_dst.s_addr == INADDR_BROADCAST || ip->ip_src.s_addr == 0 || netmask == 0 || SAMENET(ip->ip_src, ip->ip_dst, netmask)) { ea = arpwhohas(d, ip->ip_dst); } else { ea = arpwhohas(d, gateip); } return sendether(d, ip, len, ea, ETHERTYPE_IP); }
/* Caller must leave room for ethernet, ip and udp headers in front!! */ ssize_t sendudp(struct iodesc *d, void *pkt, size_t len) { ssize_t cc; struct ip *ip; struct udpiphdr *ui; struct udphdr *uh; u_char *ea; struct ip tip; #ifdef NET_DEBUG if (debug) { printf("sendudp: d=%x called.\n", (u_int)d); if (d) { printf("saddr: %s:%d", inet_ntoa(d->myip), ntohs(d->myport)); printf(" daddr: %s:%d\n", inet_ntoa(d->destip), ntohs(d->destport)); } } #endif uh = (struct udphdr *)pkt - 1; ip = (struct ip *)uh - 1; len += sizeof(*ip) + sizeof(*uh); bzero(ip, sizeof(*ip) + sizeof(*uh)); ip->ip_v = IPVERSION; /* half-char */ ip->ip_hl = sizeof(*ip) >> 2; /* half-char */ ip->ip_len = htons(len); ip->ip_p = IPPROTO_UDP; /* char */ ip->ip_ttl = IP_TTL; /* char */ ip->ip_src = d->myip; ip->ip_dst = d->destip; ip->ip_sum = in_cksum(ip, sizeof(*ip)); /* short, but special */ uh->uh_sport = d->myport; uh->uh_dport = d->destport; uh->uh_ulen = htons(len - sizeof(*ip)); /* Calculate checksum (must save and restore ip header) */ tip = *ip; ui = (struct udpiphdr *)ip; bzero(ui->ui_x1, sizeof(ui->ui_x1)); ui->ui_len = uh->uh_ulen; uh->uh_sum = in_cksum(ui, len); *ip = tip; if (ip->ip_dst.s_addr == INADDR_BROADCAST || ip->ip_src.s_addr == 0 || netmask == 0 || SAMENET(ip->ip_src, ip->ip_dst, netmask)) ea = arpwhohas(d, ip->ip_dst); else ea = arpwhohas(d, gateip); cc = sendether(d, ip, len, ea, ETHERTYPE_IP); if (cc < 0) return (-1); if ((size_t)cc != len) panic("sendudp: bad write (%d != %d)", cc, len); return (cc - (sizeof(*ip) + sizeof(*uh))); }