1 /*
2 * Copyright (c) 2003 Niels Provos <provos@citi.umich.edu>
3 * All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 */
32
33 #include <sys/types.h>
34 #include <sys/param.h>
35
36 #include "config.h"
37
38 #include <sys/queue.h>
39 #include <sys/tree.h>
40 #ifdef HAVE_SYS_TIME_H
41 #include <sys/time.h>
42 #endif
43
44 #include <err.h>
45 #include <errno.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <unistd.h>
50 #include <ctype.h>
51 #include <syslog.h>
52
53 #include <dnet.h>
54
55 #undef timeout_pending
56 #undef timeout_initialized
57
58 #include <event.h>
59
60 #include "honeyd.h"
61 #include "gre.h"
62
63 extern rand_t *honeyd_rand;
64 extern int honeyd_ttl;
65
66 static u_char pkt[IP_LEN_MAX];
67
68
69 int
gre_decapsulate(struct ip_hdr * oip,u_short oiplen,struct ip_hdr ** pip,u_short * piplen)70 gre_decapsulate(struct ip_hdr *oip, u_short oiplen,
71 struct ip_hdr **pip, u_short *piplen)
72 {
73 struct gre_hdr *gre;
74 struct ip_hdr *ip;
75 u_char *end = (u_char *)oip + oiplen;
76 u_char *data;
77 uint16_t flags, proto, iplen;
78
79 gre = (struct gre_hdr *)((u_char *)oip + (oip->ip_hl << 2));
80 data = (u_char *)(gre + 1);
81
82 if (end <= data)
83 return (-1);
84
85 /* We support only RFC 2784 */
86 flags = ntohs(gre->gre_flags);
87 if ((flags & ~GRE_CHECKSUM) != 0) {
88 syslog(LOG_DEBUG,
89 "%s: dropping RFC 1701 encapsulation: flags = %x",
90 __func__, flags);
91 return (-1);
92 }
93
94 proto = ntohs(gre->gre_proto);
95 if (proto != GRE_IP4PROTO) {
96 syslog(LOG_DEBUG,
97 "%s: dropping encapsulated packet: bad protocol %d",
98 __func__, proto);
99 return (-1);
100 }
101
102 if (!(flags & GRE_CHECKSUM))
103 data = GRE_NOCKSUM_DATA(gre);
104
105 /* Check for the proper length of the packet */
106 ip = (struct ip_hdr *)data;
107 if (data + sizeof(struct ip_hdr) > end)
108 return (-1);
109
110 iplen = ntohs(ip->ip_len);
111 if (data + iplen > end)
112 return (-1);
113
114 if (flags & GRE_CHECKSUM) {
115 u_int sum = gre->gre_sum, tmp;
116 gre->gre_sum = 0;
117
118 tmp = ip_cksum_add(gre, sizeof(struct gre_hdr) + iplen, 0);
119 tmp = ip_cksum_carry(tmp);
120 if (sum != tmp) {
121 syslog(LOG_INFO,
122 "%s: dropping encapsulated packet: bad checksum: %x vs %x",
123 __func__, ntohs(sum), ntohs(tmp));
124 return (-1);
125 }
126 }
127
128 *pip = ip;
129 *piplen = iplen;
130
131 return (0);
132 }
133
134 int
gre_encapsulate(ip_t * honeyd_ip,struct addr * src,struct addr * dst,struct ip_hdr * iip,u_int iiplen)135 gre_encapsulate(ip_t *honeyd_ip, struct addr *src, struct addr *dst,
136 struct ip_hdr *iip, u_int iiplen)
137 {
138 struct ip_hdr *oip = (struct ip_hdr *)pkt;
139 struct gre_hdr *gre = (struct gre_hdr *)(oip + 1);
140 u_char *data = (u_char *)(gre + 1);
141 u_int iplen, sum;
142
143 iplen = sizeof(struct ip_hdr) + sizeof(struct gre_hdr) + iiplen;
144
145 if (iplen > sizeof(pkt)) {
146 syslog(LOG_ERR, "%s: packet too long: %d", __func__, iplen);
147 return (-1);
148 }
149
150 ip_pack_hdr(pkt, 0, iplen, rand_uint16(honeyd_rand),
151 0, honeyd_ttl, IP_PROTO_GRE, src->addr_ip, dst->addr_ip);
152
153 memset(gre, 0, sizeof(struct gre_hdr));
154 gre->gre_flags = htons(GRE_CHECKSUM | GRE_VERSION);
155 gre->gre_proto = htons(GRE_IP4PROTO);
156
157 /* Copy the payload */
158 memcpy(data, iip, iiplen);
159
160 /* Calculate the checksum */
161 sum = ip_cksum_add(gre, iiplen + sizeof(struct gre_hdr), 0);
162 gre->gre_sum = ip_cksum_carry(sum);
163
164 ip_checksum(oip, iplen);
165
166 return (ip_send(honeyd_ip, pkt, iplen) != iplen ? -1 : 0);
167 }
168