Project Alice
Loading...
Searching...
No Matches
pcp_server_discovery.c
Go to the documentation of this file.
1/*
2 Copyright (c) 2014 by Cisco Systems, Inc.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 1. Redistributions of source code must retain the above copyright notice, this
9 list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright notice,
11 this list of conditions and the following disclaimer in the documentation
12 and/or other materials provided with the distribution.
13
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifdef HAVE_CONFIG_H
27#include "config.h"
28#else
29#include "default_config.h"
30#endif
31
32#include <stddef.h>
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <errno.h>
37
38#ifdef WIN32
40#else
41#include <stdint.h>
42#include <sys/socket.h>
43#include <netinet/in.h>
44#include <arpa/inet.h>
45#endif //WIN32
46#include "pcp.h"
47#include "pcp_utils.h"
49#include "pcp_event_handler.h"
50#include "net/gateway.h"
51#include "pcp_msg.h"
52#include "pcp_logger.h"
53#include "net/findsaddr.h"
54#include "net/pcp_socket.h"
55
56static pcp_errno psd_fill_pcp_server_src(pcp_server_t *s)
57{
58 struct in6_addr src_ip;
59 const char *err=NULL;
60
62
63 if (!s) {
65 return PCP_ERR_BAD_ARGS;
66 }
67
68 memset(&s->pcp_server_saddr, 0, sizeof(s->pcp_server_saddr));
69 memset(&src_ip, 0, sizeof(src_ip));
70
71#ifndef PCP_USE_IPV6_SOCKET
72 s->pcp_server_saddr.ss_family=AF_INET;
73 if (s->af == AF_INET) {
74 ((struct sockaddr_in *)&s->pcp_server_saddr)->sin_addr.s_addr=
75 s->pcp_ip[3];
76 ((struct sockaddr_in *)&s->pcp_server_saddr)->sin_port=s->pcp_port;
77 SET_SA_LEN(&s->pcp_server_saddr, sizeof(struct sockaddr_in));
78 inet_ntop(AF_INET,
79 (void *)&((struct sockaddr_in *)&s->pcp_server_saddr)->sin_addr,
80 s->pcp_server_paddr, sizeof(s->pcp_server_paddr));
81
82 err=findsaddr((struct sockaddr_in *)&s->pcp_server_saddr, &src_ip);
83 if (err) {
85 "Error (%s) occurred while registering a new "
86 "PCP server %s", err, s->pcp_server_paddr);
87
89 return PCP_ERR_UNKNOWN;
90 }
91 s->src_ip[0]=0;
92
93 s->src_ip[1]=0;
94 s->src_ip[2]=htonl(0xFFFF);
95 s->src_ip[3]=S6_ADDR32(&src_ip)[3];
96 } else {
98 "IPv6 is disabled and IPv6 address of PCP server occurred");
99
101 return PCP_ERR_BAD_AFINET;
102 }
103#else //PCP_USE_IPV6_SOCKET
104 s->pcp_server_saddr.ss_family=AF_INET6;
105 if (s->af == AF_INET) {
106 return PCP_ERR_BAD_AFINET; //should never happen
107 }
108 pcp_fill_sockaddr((struct sockaddr *)&s->pcp_server_saddr,
109 (struct in6_addr *)&s->pcp_ip, s->pcp_port, 1, s->pcp_scope_id);
110
111 inet_ntop(AF_INET6,
112 (void *)&((struct sockaddr_in6*) &s->pcp_server_saddr)->sin6_addr,
113 s->pcp_server_paddr, sizeof(s->pcp_server_paddr));
114
115 err=findsaddr6((struct sockaddr_in6*)&s->pcp_server_saddr, &src_ip);
116 if (err) {
118 "Error (%s) occurred while registering a new "
119 "PCP server %s", err, s->pcp_server_paddr);
120
122 return PCP_ERR_UNKNOWN;
123 }
124 s->src_ip[0]=S6_ADDR32(&src_ip)[0];
125 s->src_ip[1]=S6_ADDR32(&src_ip)[1];
126 s->src_ip[2]=S6_ADDR32(&src_ip)[2];
127 s->src_ip[3]=S6_ADDR32(&src_ip)[3];
128#endif //PCP_USE_IPV6_SOCKET
130 s->next_timeout.tv_sec=0;
131 s->next_timeout.tv_usec=0;
132
134 return PCP_ERR_SUCCESS;
135}
136
138{
139 struct sockaddr_in6 *gws=NULL, *gw;
140 int rcount=getgateways(&gws);
141
142 gw=gws;
143
144 for (; rcount > 0; rcount--, gw++) {
145 int pcps_indx;
146
147 if ((IN6_IS_ADDR_V4MAPPED(&gw->sin6_addr)) && (S6_ADDR32(&gw->sin6_addr)[3] == INADDR_ANY))
148 continue;
149
150 if (IN6_IS_ADDR_UNSPECIFIED(&gw->sin6_addr))
151 continue;
152
153 if (get_pcp_server_by_ip(ctx, &gw->sin6_addr))
154 continue;
155
156 pcps_indx=pcp_new_server(ctx, &gw->sin6_addr, ntohs(PCP_SERVER_PORT), gw->sin6_scope_id);
157 if (pcps_indx >= 0) {
158 pcp_server_t *s=get_pcp_server(ctx, pcps_indx);
159 if (!s)
160 continue;
161
162 if (psd_fill_pcp_server_src(s)) {
164 "Failed to initialize gateway %s as a PCP server.",
165 s?s->pcp_server_paddr:"NULL pointer!!!");
166 } else {
167 PCP_LOG(PCP_LOGLVL_INFO, "Found gateway %s. "
168 "Added as possible PCP server.",
169 s?s->pcp_server_paddr:"NULL pointer!!!");
170 }
171 }
172 }
173 free(gws);
174}
175
176pcp_errno psd_add_pcp_server(pcp_ctx_t *ctx, struct sockaddr *sa,
177 uint8_t version)
178{
179 struct in6_addr pcp_ip=IN6ADDR_ANY_INIT;
180 uint16_t pcp_port;
181 uint32_t scope_id=0;
182 pcp_server_t *pcps=NULL;
183
185
186 if (sa->sa_family == AF_INET) {
187 S6_ADDR32(&pcp_ip)[0]=0;
188 S6_ADDR32(&pcp_ip)[1]=0;
189 S6_ADDR32(&pcp_ip)[2]=htonl(0xFFFF);
190 S6_ADDR32(&pcp_ip)[3]=((struct sockaddr_in *)sa)->sin_addr.s_addr;
191 pcp_port=((struct sockaddr_in *)sa)->sin_port;
192 } else {
193 IPV6_ADDR_COPY(&pcp_ip, &((struct sockaddr_in6*)sa)->sin6_addr);
194 pcp_port=((struct sockaddr_in6 *)sa)->sin6_port;
195 scope_id=((struct sockaddr_in6 *)sa)->sin6_scope_id;
196 }
197
198 if (!pcp_port) {
199 pcp_port=ntohs(PCP_SERVER_PORT);
200 }
201
202 pcps=get_pcp_server_by_ip(ctx, (struct in6_addr *)&pcp_ip);
203 if (!pcps) {
204 int pcps_indx=pcp_new_server(ctx, &pcp_ip, pcp_port, scope_id);
205
206 if (pcps_indx >= 0) {
207 pcps=get_pcp_server(ctx, pcps_indx);
208 }
209
210 if (pcps == NULL) {
211 PCP_LOG(PCP_LOGLVL_ERR, "%s", "Can't add PCP server.\n");
213 return PCP_ERR_UNKNOWN;
214 }
215 } else {
216 pcps->pcp_port=pcp_port;
217 }
218
219 pcps->pcp_version=version;
221
222 if (psd_fill_pcp_server_src(pcps)) {
224 PCP_LOG(PCP_LOGLVL_INFO, "Failed to add PCP server %s",
225 pcps->pcp_server_paddr);
226
228 return PCP_ERR_UNKNOWN;
229 }
230
231 PCP_LOG(PCP_LOGLVL_INFO, "Added PCP server %s", pcps->pcp_server_paddr);
232
234 return (pcp_errno)pcps->index;
235}
#define PCP_SERVER_PORT
const char * findsaddr6(const struct sockaddr_in6 *to, struct in6_addr *from)
const char * findsaddr(const struct sockaddr_in *to, struct in6_addr *from)
Definition: findsaddr-udp.c:71
int getgateways(struct sockaddr_in6 **gws)
uint uint32_t
uchar uint8_t
@ PCP_LOGLVL_ERR
Definition: pcp.h:86
@ PCP_LOGLVL_DEBUG
Definition: pcp.h:90
@ PCP_LOGLVL_INFO
Definition: pcp.h:88
@ PCP_LOGLVL_WARN
Definition: pcp.h:87
pcp_errno
Definition: pcp.h:65
@ PCP_ERR_SUCCESS
Definition: pcp.h:66
@ PCP_ERR_BAD_ARGS
Definition: pcp.h:74
@ PCP_ERR_UNKNOWN
Definition: pcp.h:75
@ PCP_ERR_BAD_AFINET
Definition: pcp.h:69
pcp_server_t * get_pcp_server(pcp_ctx_t *ctx, int pcp_server_index)
pcp_server_t * get_pcp_server_by_ip(pcp_ctx_t *ctx, struct in6_addr *ip)
int pcp_new_server(pcp_ctx_t *ctx, struct in6_addr *ip, uint16_t port, uint32_t scope_id)
@ pss_ping
@ pss_unitialized
@ pss_allocated
#define PCP_LOG_END(level)
Definition: pcp_logger.h:73
#define PCP_LOG_BEGIN(level)
Definition: pcp_logger.h:75
#define PCP_LOG(level, fmt,...)
Definition: pcp_logger.h:71
pcp_errno psd_add_pcp_server(pcp_ctx_t *ctx, struct sockaddr *sa, uint8_t version)
void psd_add_gws(pcp_ctx_t *ctx)
void pcp_fill_sockaddr(struct sockaddr *dst, struct in6_addr *sip, uint16_t sport, int ret_ipv6_mapped_ipv4, uint32_t scope_id)
Definition: pcp_socket.c:132
#define SET_SA_LEN(s, l)
Definition: pcp_socket.h:119
#define S6_ADDR32(sa6)
Definition: pcp_utils.h:114
#define IPV6_ADDR_COPY(dest, src)
Definition: pcp_utils.h:117
#define inet_ntop
uint32_t index
uint16_t pcp_port
uint32_t pcp_ip[4]
struct timeval next_timeout
uint8_t pcp_version
struct sockaddr_storage pcp_server_saddr
pcp_server_state_e server_state
uint32_t af
uint32_t pcp_scope_id
char pcp_server_paddr[INET6_ADDRSTRLEN]
uint32_t src_ip[4]