1 /*
2 * Copyright (C) 2011, 2012, 2013 Citrix Systems
3 *
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the project nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31 #include "ns_turn_msg_addr.h"
32
33 //////////////////////////////////////////////////////////////////////////////
34
stun_addr_encode(const ioa_addr * ca,uint8_t * cfield,int * clen,int xor_ed,uint32_t mc,const uint8_t * tsx_id)35 int stun_addr_encode(const ioa_addr* ca, uint8_t *cfield, int *clen, int xor_ed, uint32_t mc, const uint8_t *tsx_id) {
36
37 if(!cfield || !clen || !ca || !tsx_id) return -1;
38
39 if (ca->ss.sa_family == AF_INET || ca->ss.sa_family==0) {
40
41 /* IPv4 address */
42
43 *clen=8;
44
45 cfield[0]=0;
46 cfield[1]=1; //IPv4 family
47
48 if (xor_ed) {
49
50 /* Port */
51 ((uint16_t*)cfield)[1] = (ca->s4.sin_port) ^ nswap16(mc >> 16);
52
53 /* Address */
54 ((uint32_t*)cfield)[1] = (ca->s4.sin_addr.s_addr) ^ nswap32(mc);
55
56 } else {
57
58 /* Port */
59 ((uint16_t*)cfield)[1]=ca->s4.sin_port;
60
61 /* Address */
62 ((uint32_t*)cfield)[1]=ca->s4.sin_addr.s_addr;
63 }
64
65 } else if (ca->ss.sa_family == AF_INET6) {
66
67 /* IPv6 address */
68
69 *clen=20;
70
71 cfield[0]=0;
72 cfield[1]=2; //IPv6 family
73
74 if (xor_ed) {
75
76 unsigned int i;
77 uint8_t *dst = ((uint8_t*)cfield)+4;
78 const uint8_t *src = (const uint8_t*)&(ca->s6.sin6_addr);
79 uint32_t magic = nswap32(mc);
80
81 /* Port */
82 ((uint16_t*)cfield)[1] = ca->s6.sin6_port ^ nswap16(mc >> 16);
83
84 /* Address */
85
86 for (i=0; i<4; ++i) {
87 dst[i] = (uint8_t)(src[i] ^ ((const uint8_t*)&magic)[i]);
88 }
89 for (i=0; i<12; ++i) {
90 dst[i+4] = (uint8_t)(src[i+4] ^ tsx_id[i]);
91 }
92
93 } else {
94
95 /* Port */
96 ((uint16_t*)cfield)[1]=ca->s6.sin6_port;
97
98 /* Address */
99 bcopy(&ca->s6.sin6_addr, ((uint8_t*)cfield)+4, 16);
100 }
101
102 } else {
103 return -1;
104 }
105
106 return 0;
107 }
108
stun_addr_decode(ioa_addr * ca,const uint8_t * cfield,int len,int xor_ed,uint32_t mc,const uint8_t * tsx_id)109 int stun_addr_decode(ioa_addr* ca, const uint8_t *cfield, int len, int xor_ed, uint32_t mc, const uint8_t *tsx_id) {
110
111 if(!cfield || !len || !ca || !tsx_id || (len<8)) return -1;
112
113 if(cfield[0]!=0) {
114 return -1;
115 }
116
117 int sa_family;
118
119 if(cfield[1]==1) sa_family=AF_INET;
120 else if(cfield[1]==2) sa_family=AF_INET6;
121 else return -1;
122
123 ca->ss.sa_family=sa_family;
124
125 if (sa_family == AF_INET) {
126
127 if(len!=8) return -1;
128
129 /* IPv4 address */
130
131 /* Port */
132 ca->s4.sin_port=((const uint16_t*)cfield)[1];
133
134 /* Address */
135 ca->s4.sin_addr.s_addr=((const uint32_t*)cfield)[1];
136
137 if (xor_ed) {
138 ca->s4.sin_port ^= nswap16(mc >> 16);
139 ca->s4.sin_addr.s_addr ^= nswap32(mc);
140 }
141
142 } else if (sa_family == AF_INET6) {
143
144 /* IPv6 address */
145
146 if(len!=20) return -1;
147
148 /* Port */
149 ca->s6.sin6_port = ((const uint16_t*)cfield)[1];
150
151 /* Address */
152 bcopy(((const uint8_t*)cfield)+4, &ca->s6.sin6_addr, 16);
153
154 if (xor_ed) {
155
156 unsigned int i;
157 uint8_t *dst;
158 const uint8_t *src;
159 uint32_t magic = nswap32(mc);
160
161 /* Port */
162 ca->s6.sin6_port ^= nswap16(mc >> 16);
163
164 /* Address */
165 src = ((const uint8_t*)cfield)+4;
166 dst = (uint8_t*)&ca->s6.sin6_addr;
167 for (i=0; i<4; ++i) {
168 dst[i] = (uint8_t)(src[i] ^ ((const uint8_t*)&magic)[i]);
169 }
170 for (i=0; i<12; ++i) {
171 dst[i+4] = (uint8_t)(src[i+4] ^ tsx_id[i]);
172 }
173 }
174
175 } else {
176 return -1;
177 }
178
179 return 0;
180 }
181
182 //////////////////////////////////////////////////////////////////////////////
183
184