source: mainline/uspace/lib/net/tl/tl_common.c@ 7c8267b

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 7c8267b was 7c8267b, checked in by Jakub Jermar <jakub@…>, 15 years ago

Coding style fixes.

This changeset converts the entire TCP code into HelenOS cstyle and improves
its general legibility by adding vertical spacing and removing unnecessary
clutter. It also attempts to suppress too deep nesting of blocks by
functional-equivalent code restructuralization.

This changeset brings no change in functionality (hopefully), but it should make
it easier to understand and eventually fix TCP code.

  • Property mode set to 100644
File size: 7.2 KB
Line 
1/*
2 * Copyright (c) 2008 Lukas Mejdrech
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
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - 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 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup net_tl
30 * @{
31 */
32
33/** @file
34 * Transport layer common functions implementation.
35 * @see tl_common.h
36 */
37
38#include <async.h>
39#include <ipc/services.h>
40
41#include <net_err.h>
42#include <packet/packet.h>
43#include <packet/packet_client.h>
44#include <packet_remote.h>
45#include <net_device.h>
46#include <icmp_interface.h>
47#include <in.h>
48#include <in6.h>
49#include <inet.h>
50#include <ip_local.h>
51#include <ip_remote.h>
52#include <socket_codes.h>
53#include <socket_errno.h>
54#include <ip_interface.h>
55#include <tl_interface.h>
56#include <tl_common.h>
57
58DEVICE_MAP_IMPLEMENT(packet_dimensions, packet_dimension_t);
59
60int tl_get_address_port(const struct sockaddr * addr, int addrlen, uint16_t * port){
61 const struct sockaddr_in * address_in;
62 const struct sockaddr_in6 * address_in6;
63
64 if((addrlen <= 0) || ((size_t) addrlen < sizeof(struct sockaddr))){
65 return EINVAL;
66 }
67 switch(addr->sa_family){
68 case AF_INET:
69 if(addrlen != sizeof(struct sockaddr_in)){
70 return EINVAL;
71 }
72 address_in = (struct sockaddr_in *) addr;
73 *port = ntohs(address_in->sin_port);
74 break;
75 case AF_INET6:
76 if(addrlen != sizeof(struct sockaddr_in6)){
77 return EINVAL;
78 }
79 address_in6 = (struct sockaddr_in6 *) addr;
80 *port = ntohs(address_in6->sin6_port);
81 break;
82 default:
83 return EAFNOSUPPORT;
84 }
85 return EOK;
86}
87
88/** Get IP packet dimensions.
89 *
90 * Try to search a cache and query the IP module if not found.
91 * The reply is cached then.
92 *
93 * @param[in] ip_phone The IP moduel phone for (semi)remote calls.
94 * @param[in] packet_dimensions The packet dimensions cache.
95 * @param[in] device_id The device identifier.
96 * @param[out] packet_dimension The IP packet dimensions.
97 *
98 * @return EOK on success.
99 * @return EBADMEM if the packet_dimension parameter is NULL.
100 * @return ENOMEM if there is not enough memory left.
101 * @return EINVAL if the packet_dimensions cache is not valid.
102 * @return Other codes as defined for the ip_packet_size_req() function.
103 *
104 */
105int tl_get_ip_packet_dimension(int ip_phone,
106 packet_dimensions_ref packet_dimensions, device_id_t device_id,
107 packet_dimension_ref *packet_dimension)
108{
109 ERROR_DECLARE;
110
111 if (!packet_dimension)
112 return EBADMEM;
113
114 *packet_dimension = packet_dimensions_find(packet_dimensions, device_id);
115 if (!*packet_dimension) {
116 /* Ask for and remember them if not found */
117 *packet_dimension = malloc(sizeof(**packet_dimension));
118 if(!*packet_dimension)
119 return ENOMEM;
120
121 if (ERROR_OCCURRED(ip_packet_size_req(ip_phone, device_id,
122 *packet_dimension))) {
123 free(*packet_dimension);
124 return ERROR_CODE;
125 }
126
127 ERROR_CODE = packet_dimensions_add(packet_dimensions, device_id,
128 *packet_dimension);
129 if (ERROR_CODE < 0) {
130 free(*packet_dimension);
131 return ERROR_CODE;
132 }
133 }
134
135 return EOK;
136}
137
138int tl_update_ip_packet_dimension(packet_dimensions_ref packet_dimensions, device_id_t device_id, size_t content){
139 packet_dimension_ref packet_dimension;
140
141 packet_dimension = packet_dimensions_find(packet_dimensions, device_id);
142 if(! packet_dimension){
143 return ENOENT;
144 }
145 packet_dimension->content = content;
146 if(device_id != DEVICE_INVALID_ID){
147 packet_dimension = packet_dimensions_find(packet_dimensions, DEVICE_INVALID_ID);
148 if(packet_dimension){
149 if(packet_dimension->content >= content){
150 packet_dimension->content = content;
151 }else{
152 packet_dimensions_exclude(packet_dimensions, DEVICE_INVALID_ID);
153 }
154 }
155 }
156 return EOK;
157}
158
159int tl_set_address_port(struct sockaddr * addr, int addrlen, uint16_t port)
160{
161 struct sockaddr_in * address_in;
162 struct sockaddr_in6 * address_in6;
163 size_t length;
164
165 if (addrlen < 0)
166 return EINVAL;
167
168 length = (size_t) addrlen;
169 if (length < sizeof(struct sockaddr))
170 return EINVAL;
171
172 switch (addr->sa_family) {
173 case AF_INET:
174 if (length != sizeof(struct sockaddr_in))
175 return EINVAL;
176 address_in = (struct sockaddr_in *) addr;
177 address_in->sin_port = htons(port);
178 return EOK;
179 case AF_INET6:
180 if (length != sizeof(struct sockaddr_in6))
181 return EINVAL;
182 address_in6 = (struct sockaddr_in6 *) addr;
183 address_in6->sin6_port = htons(port);
184 return EOK;
185 default:
186 return EAFNOSUPPORT;
187 }
188}
189
190int tl_prepare_icmp_packet(int packet_phone, int icmp_phone, packet_t packet, services_t error){
191 packet_t next;
192 uint8_t * src;
193 int length;
194
195 // detach the first packet and release the others
196 next = pq_detach(packet);
197 if (next)
198 pq_release_remote(packet_phone, packet_get_id(next));
199
200 length = packet_get_addr(packet, &src, NULL);
201 if((length > 0)
202 && (! error)
203 && (icmp_phone >= 0)
204 // set both addresses to the source one (avoids the source address deletion before setting the destination one)
205 && (packet_set_addr(packet, src, src, (size_t) length) == EOK)){
206 return EOK;
207 }else{
208 pq_release_remote(packet_phone, packet_get_id(packet));
209 }
210 return ENOENT;
211}
212
213int tl_socket_read_packet_data(int packet_phone, packet_ref packet, size_t prefix, const packet_dimension_ref dimension, const struct sockaddr * addr, socklen_t addrlen){
214 ERROR_DECLARE;
215
216 ipc_callid_t callid;
217 size_t length;
218 void * data;
219
220 if(! dimension){
221 return EINVAL;
222 }
223 // get the data length
224 if(! async_data_write_receive(&callid, &length)){
225 return EINVAL;
226 }
227 // get a new packet
228 *packet = packet_get_4_remote(packet_phone, length, dimension->addr_len, prefix + dimension->prefix, dimension->suffix);
229 if(! packet){
230 return ENOMEM;
231 }
232 // allocate space in the packet
233 data = packet_suffix(*packet, length);
234 if(! data){
235 pq_release_remote(packet_phone, packet_get_id(*packet));
236 return ENOMEM;
237 }
238 // read the data into the packet
239 if(ERROR_OCCURRED(async_data_write_finalize(callid, data, length))
240 // set the packet destination address
241 || ERROR_OCCURRED(packet_set_addr(*packet, NULL, (uint8_t *) addr, addrlen))){
242 pq_release_remote(packet_phone, packet_get_id(*packet));
243 return ERROR_CODE;
244 }
245 return (int) length;
246}
247
248/** @}
249 */
Note: See TracBrowser for help on using the repository browser.