/* * The mrouted program is covered by the license in the accompanying file * named "LICENSE". Use of the mrouted program represents acceptance of * the terms and conditions listed in that file. * * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of * Leland Stanford Junior University. * * * @(#) $Id ipip.c,v 3.8.4.6 1998/01/06 01:57:45 fenner Exp $ * $DragonFly: src/usr.sbin/mrouted/ipip.c,v 1.3 2004/03/15 18:10:28 dillon Exp $ */ #include "defs.h" /* * Exported variables. */ #ifdef notyet int raw_socket; /* socket for raw network I/O */ #endif /* *XXX For now, we just use the IGMP socket to send packets. * This is legal in BSD, because the protocol # is not checked * on raw sockets. The k_* interfaces need to gain a socket * argument so that we can call them on the raw_socket also. */ #define raw_socket igmp_socket /* * Private variables. */ static int rawid = 0; /* * Open and initialize the raw socket. */ void init_ipip(void) { #ifdef notyet if ((raw_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) log(LOG_ERR, errno, "Raw IP socket"); #endif } /* * Allocate and fill in static IP header for encapsulating on a tunnel. */ void init_ipip_on_vif(struct uvif *v) { struct ip *ip; ip = v->uv_encap_hdr = (struct ip *)malloc(sizeof(struct ip)); if (ip == NULL) log(LOG_ERR, 0, "out of memory"); bzero(ip, sizeof(struct ip)); /* * Fields zeroed that aren't filled in later: * - IP ID (let the kernel fill it in) * - Offset (we don't send fragments) * - Checksum (let the kernel fill it in) */ ip->ip_v = IPVERSION; ip->ip_hl = sizeof(struct ip) >> 2; ip->ip_tos = 0xc0; /* Internet Control */ ip->ip_ttl = MAXTTL; /* applies to unicasts only */ ip->ip_p = IPPROTO_IPIP; ip->ip_src.s_addr = v->uv_lcl_addr; ip->ip_dst.s_addr = v->uv_rmt_addr; } /* * Call build_igmp() to build an IGMP message in the output packet buffer. * Then fill in the fields of the IP packet that build_igmp() left for the * kernel to fill in, and encapsulate the original packet with the * pre-created ip header for this vif. */ void send_ipip(u_int32 src, u_int32 dst, int type, int code, u_int32 group, int datalen, struct uvif *v) { struct msghdr msg; struct iovec iov[2]; struct sockaddr_in sdst; struct ip *ip; build_igmp(src, dst, type, code, group, datalen); ip = (struct ip *)send_buf; #ifndef RAW_OUTPUT_IS_RAW ip->ip_len = htons(ip->ip_len); #endif ip->ip_id = htons(rawid++); ip->ip_sum = 0; ip->ip_sum = inet_cksum((u_short *)ip, ip->ip_hl << 2); ip = v->uv_encap_hdr; ip->ip_len = 2 * MIN_IP_HEADER_LEN + IGMP_MINLEN + datalen; #ifdef RAW_OUTPUT_IS_RAW ip->ip_len = htons(ip->ip_len); #endif bzero(&sdst, sizeof(sdst)); sdst.sin_family = AF_INET; #ifdef HAVE_SA_LEN sdst.sin_len = sizeof(sdst); #endif sdst.sin_addr = ip->ip_dst; iov[0].iov_base = (caddr_t)v->uv_encap_hdr; iov[0].iov_len = sizeof(struct ip); iov[1].iov_base = (caddr_t)send_buf; iov[1].iov_len = MIN_IP_HEADER_LEN + IGMP_MINLEN + datalen; bzero(&msg, sizeof(msg)); msg.msg_name = (caddr_t)&sdst; msg.msg_namelen = sizeof(sdst); msg.msg_iov = iov; msg.msg_iovlen = 2; if (sendmsg(raw_socket, &msg, 0) < 0) { if (errno == ENETDOWN) check_vif_state(); else log(LOG_WARNING, errno, "sendmsg to %s on %s", inet_fmt(sdst.sin_addr.s_addr, s1), inet_fmt(src, s2)); } IF_DEBUG(DEBUG_PKT|igmp_debug_kind(type, code)) log(LOG_DEBUG, 0, "SENT %s from %-15s to %s encaped to %s", igmp_packet_kind(type, code), src == INADDR_ANY ? "INADDR_ANY" : inet_fmt(src, s1), inet_fmt(dst, s2), inet_fmt(sdst.sin_addr.s_addr, s3)); }