-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathip.c
86 lines (74 loc) · 1.58 KB
/
ip.c
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
#include <stdio.h>
#include <stddef.h> /* NULL */
#include "netif.h"
#include "mbuf.h"
#include "udp.h"
#include "netsniff.h"
#include "checksum.h"
#include "etherif.h"
#include "arp.h"
#include "unet.h"
static char fmt_buf[1024];
static struct strbuf sb = {
.size = sizeof(fmt_buf),
.buf = fmt_buf
};
void
ip_input(struct netif *ifp, struct mbuf *m)
{
struct iphdr *iph;
iph = mb_head(m);
if (ip_csum(iph, ip_hdrlen(iph), 0x0000) != 0) {
fprintf(stderr, "IP: bad checksum\n");
goto drop;
}
sb_reset(&sb);
if (iphdr_print(iph, &sb) == 0)
pr_dbg("ip: %s\n", sb.buf);
/* IP proto demux */
switch (iph->protocol) {
case IPPROTO_UDP:
udp_input(ifp, m);
break;
case IPPROTO_TCP:
pr_dbg("TCP\n");
/* FALLTHROUGH */
default:
goto drop;
}
return;
drop:
mb_chain_free(m);
}
static inline ipv4_t route_dst(const struct netif *ifp, uint32_t daddr)
{
if ((daddr & ifp->mask.addr) == (ifp->ipaddr.addr & ifp->mask.addr))
return (ipv4_t)daddr;
return ifp->gateway;
}
void
ip_output(struct netif *ifp, struct mbuf *m,
uint16_t id, uint8_t proto,
uint32_t saddr, uint32_t daddr)
{
struct iphdr *ih;
hwaddr_t dsteth;
ipv4_t dstip;
ih = mb_push(m, sizeof(*ih));
ih->version = 4;
ih->ihl = 5;
ih->tos = 0;
ih->tot_len = htons(mb_datalen(m));
ih->id = id;
ih->frag_off = 0;
ih->ttl = 30;
ih->protocol = proto;
ih->saddr = saddr;
ih->daddr = daddr;
/* Fill checksum field */
ih->check = 0;
ih->check = ip_csum(ih, ip_hdrlen(ih), 0);
dstip = route_dst(ifp, daddr);
if (arp_resolve(ifp, dstip, m, &dsteth))
eth_output(ifp, m, dsteth.data, ETH_P_IP);
}