summaryrefslogtreecommitdiffstats
path: root/usr.sbin/mrouted/ipip.c
blob: 6e88d932d3b4d00dec167b11700f9d1390df64ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
 * 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.
 *
 *
 * ipip.c,v 3.8.4.6 1998/01/06 01:57:45 fenner Exp
 */


#include "defs.h"

#ifndef lint
static char rcsid[] = "@(#) $Id: \
ipip.c,v 3.8.4.6 1998/01/06 01:57:45 fenner Exp $";
#endif

/*
 * 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()
{
#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(v)
    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(src, dst, type, code, group, datalen, v)
    u_int32 src, dst;
    int type, 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));
}
OpenPOWER on IntegriCloud