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