]> git.deb.at Git - pkg/netris.git/blob - debian/patches/09_ipv6
Finalize the changelog
[pkg/netris.git] / debian / patches / 09_ipv6
1 Description: Implement capability for IPv6.
2  Migration to 'getaddrinfo()' and 'struct sockaddr_storage'
3  make both address families AF_INET and AF_INET6 viable.
4  .
5  The preferred form of a port is as a string value in getaddrinfo(),
6  so named ports are no possible, alongside numerical ports.
7  .
8  The goto statement is left because the previous code enforced
9  a similar construct. It should really be removed.
10 Author: Mats Erik Andersson <debian@gisladisker.se>
11 Forwarded: no
12 Last-Updated: 2010-03-03
13
14 Index: b/inet.c
15 ===================================================================
16 --- a/inet.c
17 +++ b/inet.c
18 @@ -49,32 +49,60 @@ ExtFunc void InitNet(void)
19  
20  ExtFunc int WaitForConnection(char *portStr)
21  {
22 -       struct sockaddr_in addr;
23 -       struct hostent *host;
24 -       int sockListen;
25 +       struct sockaddr_storage addr;
26 +       struct sockaddr_in *sa4 = (struct sockaddr_in *) &addr;
27 +       struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &addr;
28 +       struct hostent *host = NULL;
29 +       struct addrinfo hints, *ai, *aiptr;
30 +       char portStrDef[12];
31 +       int sockListen, status;
32         socklen_t addrLen;
33 -       short port;
34         int val1;
35         struct linger val2;
36  
37 -       if (portStr)
38 -               port = atoi(portStr);   /* XXX Error checking */
39 -       else
40 -               port = DEFAULT_PORT;
41 -       memset(&addr, 0, sizeof(addr));
42 -       addr.sin_family = AF_INET;
43 -       addr.sin_addr.s_addr = htonl(INADDR_ANY);
44 -       addr.sin_port = htons(port);
45 -       sockListen = socket(AF_INET, SOCK_STREAM, 0);
46 -       if (sockListen < 0)
47 +       if (!portStr || !strlen(portStr)) {
48 +               snprintf(portStrDef, sizeof(portStrDef), "%u", DEFAULT_PORT);
49 +               portStr = portStrDef;
50 +       }
51 +       /* XXX Error checking of port string. */
52 +
53 +       memset(&hints, 0, sizeof(hints));
54 +       hints.ai_family = AF_INET6;
55 +       hints.ai_socktype = SOCK_STREAM;
56 +       hints.ai_flags = AI_PASSIVE;
57 +
58 +       if ( (status = getaddrinfo(NULL, portStr, &hints, &ai)) ) {
59 +               fprintf(stderr, "getaddrinfo() failed: %s\n",
60 +                               gai_strerror(status));
61 +               die("getaddrinfo");
62 +       }
63 +
64 +       for (aiptr = ai; aiptr; aiptr = aiptr->ai_next) {
65 +               if ( (sockListen = socket(aiptr->ai_family,
66 +                                               aiptr->ai_socktype,
67 +                                               aiptr->ai_protocol))
68 +                               < 0 )
69 +                       continue;
70 +
71 +               val1 = 1;
72 +               setsockopt(sockListen, SOL_SOCKET, SO_REUSEADDR,
73 +                               (void *)&val1, sizeof(val1));
74 +               val1 = 0;
75 +               setsockopt(sockListen, IPPROTO_IPV6, IPV6_V6ONLY,
76 +                               (void *)&val1, sizeof(val1));
77 +
78 +               if ( bind(sockListen, aiptr->ai_addr, aiptr->ai_addrlen)
79 +                               == 0 )
80 +                       if ( listen(sockListen, 1) >= 0 )
81 +                               break;
82 +
83 +               close(sockListen);
84 +       }
85 +
86 +       freeaddrinfo(ai);
87 +       if (aiptr == NULL)
88                 die("socket");
89 -       val1 = 1;
90 -       setsockopt(sockListen, SOL_SOCKET, SO_REUSEADDR,
91 -                       (void *)&val1, sizeof(val1));
92 -       if (bind(sockListen, (struct sockaddr *)&addr, sizeof(addr)) < 0)
93 -               die("bind");
94 -       if (listen(sockListen, 1) < 0)
95 -               die("listen");
96 +
97         addrLen = sizeof(addr);
98         sock = accept(sockListen, (struct sockaddr *)&addr, &addrLen);
99         if (sock < 0)
100 @@ -86,13 +114,18 @@ ExtFunc int WaitForConnection(char *port
101                         (void *)&val2, sizeof(val2));
102         netGen.fd = sock;
103         strcpy(opponentHost, "???");
104 -       if (addr.sin_family == AF_INET) {
105 -               host = gethostbyaddr((void *)&addr.sin_addr,
106 -                               sizeof(struct in_addr), AF_INET);
107 -               if (host) {
108 -                       strncpy(opponentHost, host->h_name, sizeof(opponentHost)-1);
109 -                       opponentHost[sizeof(opponentHost)-1] = 0;
110 -               }
111 +       switch (addr.ss_family) {
112 +               case AF_INET6:
113 +                       host = gethostbyaddr((void *)&sa6->sin6_addr,
114 +                               sizeof(struct in6_addr), addr.ss_family);
115 +                       break;
116 +               case AF_INET:
117 +                       host = gethostbyaddr((void *)&sa4->sin_addr,
118 +                               sizeof(struct in_addr), addr.ss_family);
119 +       }
120 +       if (host) {
121 +               strncpy(opponentHost, host->h_name, sizeof(opponentHost)-1);
122 +               opponentHost[sizeof(opponentHost)-1] = 0;
123         }
124         AddEventGen(&netGen);
125         isServer = 1;
126 @@ -101,36 +134,54 @@ ExtFunc int WaitForConnection(char *port
127  
128  ExtFunc int InitiateConnection(char *hostStr, char *portStr)
129  {
130 -       struct sockaddr_in addr;
131 -       struct hostent *host;
132 -       short port;
133 -       int mySock;
134 -
135 -       if (portStr)
136 -               port = atoi(portStr);   /* XXX Error checking */
137 -       else
138 -               port = DEFAULT_PORT;
139 -       host = gethostbyname(hostStr);
140 -       if (!host)
141 -               die("gethostbyname");
142 -       assert(host->h_addrtype == AF_INET);
143 -       strncpy(opponentHost, host->h_name, sizeof(opponentHost)-1);
144 -       opponentHost[sizeof(opponentHost)-1] = 0;
145 - again:
146 -       memset(&addr, 0, sizeof(addr));
147 -       addr.sin_family = host->h_addrtype;
148 -       memcpy(&addr.sin_addr, host->h_addr, host->h_length);
149 -       addr.sin_port = htons(port);
150 -       mySock = socket(AF_INET, SOCK_STREAM, 0);
151 -       if (mySock < 0)
152 -               die("socket");
153 -       if (connect(mySock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
154 -               if (errno != ECONNREFUSED)
155 -                       die("connect");
156 +       struct addrinfo hints, *ai, *aiptr;
157 +       char portStrDef[12];
158 +       int mySock, status;
159 +
160 +       if (!portStr || !strlen(portStr)) {
161 +               snprintf(portStrDef, sizeof(portStrDef), "%u", DEFAULT_PORT);
162 +               portStr = portStrDef;
163 +       }
164 +       /* XXX Error checking of port string. */
165 +
166 +       memset(&hints, 0, sizeof(hints));
167 +       hints.ai_family = AF_UNSPEC;
168 +       hints.ai_socktype = SOCK_STREAM;
169 +       hints.ai_flags = AI_ADDRCONFIG | AI_CANONNAME;
170 +
171 +       if ( (status = getaddrinfo(hostStr, portStr, &hints, &ai)) ) {
172 +               fprintf(stderr, "getaddrinfo() failed: %s\n",
173 +                               gai_strerror(status));
174 +               die("getaddrinfo");
175 +       }
176 +
177 +       for (aiptr = ai; aiptr; aiptr = aiptr->ai_next) {
178 +again:
179 +               if ( (mySock = socket(aiptr->ai_family, aiptr->ai_socktype,
180 +                                               aiptr->ai_protocol))
181 +                               < 0 )
182 +                       continue;
183 +               while ( (status = connect(mySock, aiptr->ai_addr,
184 +                                               aiptr->ai_addrlen)) < 0
185 +                               && errno == ECONNREFUSED ) {
186 +                       close(mySock);
187 +                       sleep(1);
188 +                       goto again;
189 +               }
190 +               if (status >= 0)
191 +                       break;
192 +               /* Failure to connect. */
193                 close(mySock);
194 -               sleep(1);
195 -               goto again;
196         }
197 +
198 +       if (aiptr == NULL) {
199 +               freeaddrinfo(ai);
200 +               die("socket/connect");
201 +       }
202 +
203 +       strncpy(opponentHost, aiptr->ai_canonname, sizeof(opponentHost)-1);
204 +       opponentHost[sizeof(opponentHost)-1] = 0;
205 +       freeaddrinfo(ai);
206         netGen.fd = sock = mySock;
207         AddEventGen(&netGen);
208         return 0;