-
Notifications
You must be signed in to change notification settings - Fork 28
/
Copy pathGetUDPIP_server.c
135 lines (112 loc) · 3.64 KB
/
GetUDPIP_server.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
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
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
struct pkt_info {
struct in_addr udp_ip;
int udp_ifindex;
};
int main(int argc, char const *argv[])
{
if (argc != 2) {
printf("usage : %s <port>\n", argv[0]);
exit(1);
}
int sockfd = -1;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket error!");
exit(1);
}
struct sockaddr_in svraddr;
bzero(&svraddr, sizeof(svraddr));
svraddr.sin_family = AF_INET;
svraddr.sin_port = htons(atoi(argv[1]));
svraddr.sin_addr.s_addr = htonl(INADDR_ANY);
int recvbuf = 100 << 10;
if (setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &recvbuf, sizeof(recvbuf)) < 0) {
perror("setsockopt error!");
exit(1);
}
if (bind(sockfd, (struct sockaddr *)&svraddr, sizeof(svraddr)) < 0) {
perror("bind error!");
exit(1);
}
int on = 1;
#ifdef IP_RECVORIGDSTADDR
if (setsockopt(sockfd, IPPROTO_IP, IP_RECVORIGDSTADDR, &on, sizeof(on)) < 0) {
#elif defined(IP_RECVDSTADDR)
if (setsockopt(sockfd, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on)) < 0) {
#endif
perror("setsockopt error!");
exit(1);
}
#ifdef IF_RECVIF
if (setsockopt(sockfd, IPPROTO_IP, IP_RECVIF, &on, sizeof(on)) < 0) {
perror("setsockopt error!");
exit(1);
}
#endif
struct msghdr msg;
union {
struct msghdr msg;
char control[CMSG_SPACE(sizeof(struct sockaddr_in)) + CMSG_SPACE(sizeof(struct pkt_info))];
} control;
char buf[1024];
struct iovec iov[1];
iov[0].iov_base = buf;
iov[0].iov_len = sizeof(buf);
struct sockaddr_in cliaddr;
socklen_t clilen = sizeof(cliaddr);
struct pkt_info info;
bzero(&info, sizeof(info));
for (;;) {
bzero(&msg, sizeof(msg));
bzero(&control, sizeof(control));
bzero(&info, sizeof(info));
msg.msg_control = control.control;
msg.msg_controllen = sizeof(control);
msg.msg_flags = 0;
msg.msg_name = &cliaddr;
msg.msg_namelen = clilen;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
ssize_t nread = 0;
if ((nread = recvmsg(sockfd, &msg, 0)) < 0) {
perror("recvmsg error!");
exit(1);
}
buf[nread] = 0;
if (msg.msg_controllen < sizeof(struct cmsghdr) || (msg.msg_flags & MSG_CTRUNC)) {
printf("recvbuf len too less\n");
exit(1);
}
struct cmsghdr *ptr = NULL;
for (ptr = CMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr)) {
#ifdef IP_RECVORIGDSTADDR
if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_RECVORIGDSTADDR) {
#elif defined(IP_RECVDSTADDR)
if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_RECVDSTADDR) {
#endif
info.udp_ip = ((struct sockaddr_in *)CMSG_DATA(ptr))->sin_addr;
}
#ifdef IF_RECVIF
if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_RECVIF) {
struct sockaddr_dl *dl_addr = (struct sockaddr_dl *)CMSG_DATA(ptr);
info.udp_ifindex = dl_addr->sdl_index;
}
#endif
}
char addr[1024];
snprintf(addr, sizeof(addr), "[%s:%d]", inet_ntoa(info.udp_ip), ntohs(cliaddr.sin_port));
printf("udp req from %s, recv %ld bytes\n", addr, (long)nread);
ssize_t nwrite = 0;
if ((nwrite = sendto(sockfd, buf, nread, 0, (struct sockaddr *)&cliaddr, msg.msg_namelen)) < 0) {
perror("sendto error!");
continue;
}
}
return 0;
}