source: mainline/uspace/lib/nettl/src/portrng.c@ a53ed3a

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a53ed3a was b7fd2a0, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

Use errno_t in all uspace and kernel code.

Change type of every variable, parameter and return value that holds an
<errno.h> constant to either errno_t (the usual case), or sys_errno_t
(some places in kernel). This is for the purpose of self-documentation,
as well as for type-checking with a bit of type definition hackery.

Although this is a massive commit, it is a simple text replacement, and thus
is very easy to verify. Simply do the following:

`
git checkout <this commit's hash>
git reset HEAD
git add .
tools/srepl '\berrno_t\b' int
git add .
tools/srepl '\bsys_errno_t\b' sysarg_t
git reset
git diff
`

While this doesn't ensure that the replacements are correct, it does ensure
that the commit doesn't do anything except those replacements. Since errno_t
is typedef'd to int in the usual case (and sys_errno_t to sysarg_t), even if
incorrect, this commit cannot change behavior.

  • Property mode set to 100644
File size: 5.8 KB
Line 
1/*
2 * Copyright (c) 2015 Jiri Svoboda
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 libnettl
30 * @{
31 */
32
33/**
34 * @file Port range allocator
35 *
36 * Allocates port numbers from IETF port number ranges.
37 */
38
39#include <adt/list.h>
40#include <errno.h>
41#include <inet/endpoint.h>
42#include <nettl/portrng.h>
43#include <stdint.h>
44#include <stdlib.h>
45
46#include <io/log.h>
47
48/** Create port range.
49 *
50 * @param rpr Place to store pointer to new port range
51 * @return EOK on success, ENOMEM if out of memory
52 */
53errno_t portrng_create(portrng_t **rpr)
54{
55 portrng_t *pr;
56
57 log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_create() - begin");
58
59 pr = calloc(1, sizeof(portrng_t));
60 if (pr == NULL)
61 return ENOMEM;
62
63 list_initialize(&pr->used);
64 *rpr = pr;
65 log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_create() - end");
66 return EOK;
67}
68
69/** Destroy port range.
70 *
71 * @param pr Port range
72 */
73void portrng_destroy(portrng_t *pr)
74{
75 log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_destroy()");
76 assert(list_empty(&pr->used));
77 free(pr);
78}
79
80/** Allocate port number from port range.
81 *
82 * @param pr Port range
83 * @param pnum Port number to allocate specific port, or zero to allocate
84 * any valid port from range
85 * @param arg User argument to set for port
86 * @param flags Flags, @c pf_allow_system to allow ports from system range
87 * to be specified by @a pnum.
88 * @param apnum Place to store allocated port number
89 *
90 * @return EOK on success, ENOENT if no free port number found, EEXIST
91 * if @a pnum is specified but it is already allocated,
92 * EINVAL if @a pnum is specified from the system range, but
93 * @c pf_allow_system was not set.
94 */
95errno_t portrng_alloc(portrng_t *pr, uint16_t pnum, void *arg,
96 portrng_flags_t flags, uint16_t *apnum)
97{
98 portrng_port_t *p;
99 uint32_t i;
100 bool found;
101
102 log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_alloc() - begin");
103
104 if (pnum == inet_port_any) {
105
106 for (i = inet_port_dyn_lo; i <= inet_port_dyn_hi; i++) {
107 log_msg(LOG_DEFAULT, LVL_DEBUG2, "trying %" PRIu32, i);
108 found = false;
109 list_foreach(pr->used, lprng, portrng_port_t, port) {
110 if (port->pn == pnum) {
111 found = true;
112 break;
113 }
114 }
115
116 if (!found) {
117 pnum = i;
118 break;
119 }
120 }
121
122 if (pnum == inet_port_any) {
123 /* No free port found */
124 return ENOENT;
125 }
126 log_msg(LOG_DEFAULT, LVL_DEBUG2, "selected %" PRIu16, pnum);
127 } else {
128 log_msg(LOG_DEFAULT, LVL_DEBUG2, "user asked for %" PRIu16, pnum);
129
130 if ((flags & pf_allow_system) == 0 &&
131 pnum < inet_port_user_lo) {
132 log_msg(LOG_DEFAULT, LVL_DEBUG2, "system port not allowed");
133 return EINVAL;
134 }
135
136 list_foreach(pr->used, lprng, portrng_port_t, port) {
137 if (port->pn == pnum) {
138 log_msg(LOG_DEFAULT, LVL_DEBUG2, "port already used");
139 return EEXIST;
140 }
141 }
142 }
143
144 p = calloc(1, sizeof(portrng_port_t));
145 if (p == NULL)
146 return ENOMEM;
147
148 p->pn = pnum;
149 p->arg = arg;
150 list_append(&p->lprng, &pr->used);
151 *apnum = pnum;
152 log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_alloc() - end OK pn=%" PRIu16,
153 pnum);
154 return EOK;
155}
156
157/** Find allocated port number and return its argument.
158 *
159 * @param pr Port range
160 * @param pnum Port number
161 * @param rarg Place to store user argument
162 *
163 * @return EOK on success, ENOENT if specified port number is not allocated
164 */
165errno_t portrng_find_port(portrng_t *pr, uint16_t pnum, void **rarg)
166{
167 list_foreach(pr->used, lprng, portrng_port_t, port) {
168 if (port->pn == pnum) {
169 *rarg = port->arg;
170 return EOK;
171 }
172 }
173
174 return ENOENT;
175}
176
177/** Free port in port range.
178 *
179 * @param pr Port range
180 * @param pnum Port number
181 */
182void portrng_free_port(portrng_t *pr, uint16_t pnum)
183{
184 log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_free_port(%u)", pnum);
185 log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_free_port() - begin");
186 list_foreach(pr->used, lprng, portrng_port_t, port) {
187 log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_free_port - check port %u", port->pn);
188 if (port->pn == pnum) {
189 log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_free_port - OK");
190 list_remove(&port->lprng);
191 free(port);
192 log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_free_port() - end");
193 return;
194 }
195 }
196
197 log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_free_port - FAIL");
198 assert(false);
199}
200
201/** Determine if port range is empty.
202 *
203 * @param pr Port range
204 * @return @c true if no ports are allocated from @a pr, @c false otherwise
205 */
206bool portrng_empty(portrng_t *pr)
207{
208 log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_empty()");
209 return list_empty(&pr->used);
210}
211
212/**
213 * @}
214 */
Note: See TracBrowser for help on using the repository browser.