/* * Send an UDP packet from port sport to host ``daddr'' * and port ``dport''. The arguments are in host byte order. */ int udp_send(port_t sport, ipaddr_t daddr, port_t dport, void *data, int len) { static unsigned short ipid = 1; udphdr_t *up; char *msg; int rv, udplen; pseudohdr_t ph; extern ipaddr_t my_ipaddr; if (!my_ipaddr && !ip_init()) return -1; if (extra_info()) { printf("udp_send(%d, %s, %d, %p, %d)\n", sport, inet_ntoa(daddr), dport, data, len); } udplen = len + sizeof(udphdr_t); if ((msg = malloc(align(udplen))) == NULL) { printf("%s, %d: malloc failed\n", __LINE__, __FILE__); return -1; } up = (udphdr_t *) msg; up->uh_sport = htons(sport); up->uh_dport = htons(dport); up->uh_len = htons(udplen); up->uh_sum = 0; memcpy(msg + sizeof(udphdr_t), data, len); /* compute UDP checksum */ ph.ph_src = my_ipaddr; ph.ph_dst = daddr; ph.ph_zero = 0; ph.ph_p = IP_PROTO_UDP; ph.ph_len = up->uh_len; up->uh_sum = ~inet_checksum(&ph, sizeof(ph)); if (udplen & 1) msg[udplen] = '\0'; up->uh_sum = inet_checksum(up, align(udplen)); if (up->uh_sum == 0) up->uh_sum = 0xFFFF; rv = ip_send(daddr, IP_PROTO_UDP, ipid++, msg, udplen); free(msg); /* return rv; */ return len; }
int tcp_opt_apply(void *d, struct pktq *pktq, struct rule **next_rule) { struct tcp_opt *opt = (struct tcp_opt *)d; struct pkt *pkt; size_t len; TAILQ_FOREACH(pkt, pktq, pkt_next) { uint16_t eth_type = htons(pkt->pkt_eth->eth_type); len = inet_add_option(eth_type, pkt->pkt_ip, sizeof(pkt->pkt_data) - ETH_HDR_LEN, IP_PROTO_TCP, opt, opt->opt_len); if (len > 0) { pkt->pkt_end += len; pkt_decorate(pkt); inet_checksum(eth_type, pkt->pkt_ip, pkt->pkt_end - pkt->pkt_eth_data); } }