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

Last change on this file 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
RevLine 
[4794417]1/*
[2f19103]2 * Copyright (c) 2015 Jiri Svoboda
[4794417]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
[2989c7e]29/** @addtogroup libnettl
[4794417]30 * @{
31 */
[2989c7e]32
33/**
34 * @file Port range allocator
35 *
36 * Allocates port numbers from IETF port number ranges.
[4794417]37 */
38
[ab6326bc]39#include <adt/list.h>
[2989c7e]40#include <errno.h>
[ab6326bc]41#include <inet/endpoint.h>
[2989c7e]42#include <nettl/portrng.h>
43#include <stdint.h>
[ab6326bc]44#include <stdlib.h>
45
46#include <io/log.h>
[2989c7e]47
[b10460a]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 */
[b7fd2a0]53errno_t portrng_create(portrng_t **rpr)
[2989c7e]54{
[ab6326bc]55 portrng_t *pr;
56
[c3f7d37]57 log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_create() - begin");
[ab6326bc]58
59 pr = calloc(1, sizeof(portrng_t));
60 if (pr == NULL)
61 return ENOMEM;
62
63 list_initialize(&pr->used);
64 *rpr = pr;
[c3f7d37]65 log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_create() - end");
[2989c7e]66 return EOK;
67}
68
[b10460a]69/** Destroy port range.
70 *
71 * @param pr Port range
72 */
[2989c7e]73void portrng_destroy(portrng_t *pr)
74{
[c3f7d37]75 log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_destroy()");
[ab6326bc]76 assert(list_empty(&pr->used));
77 free(pr);
[2989c7e]78}
79
[b10460a]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 *
[8a637a4]90 * @return EOK on success, ENOENT if no free port number found, EEXIST
[b10460a]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 */
[b7fd2a0]95errno_t portrng_alloc(portrng_t *pr, uint16_t pnum, void *arg,
[ab6326bc]96 portrng_flags_t flags, uint16_t *apnum)
[2989c7e]97{
[ab6326bc]98 portrng_port_t *p;
99 uint32_t i;
100 bool found;
101
[c3f7d37]102 log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_alloc() - begin");
[ab6326bc]103
104 if (pnum == inet_port_any) {
105
106 for (i = inet_port_dyn_lo; i <= inet_port_dyn_hi; i++) {
[c3f7d37]107 log_msg(LOG_DEFAULT, LVL_DEBUG2, "trying %" PRIu32, i);
[ab6326bc]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 }
[c3f7d37]126 log_msg(LOG_DEFAULT, LVL_DEBUG2, "selected %" PRIu16, pnum);
[ab6326bc]127 } else {
[c3f7d37]128 log_msg(LOG_DEFAULT, LVL_DEBUG2, "user asked for %" PRIu16, pnum);
[1ede059]129
[ab6326bc]130 if ((flags & pf_allow_system) == 0 &&
131 pnum < inet_port_user_lo) {
[c3f7d37]132 log_msg(LOG_DEFAULT, LVL_DEBUG2, "system port not allowed");
[ab6326bc]133 return EINVAL;
134 }
135
136 list_foreach(pr->used, lprng, portrng_port_t, port) {
[1ede059]137 if (port->pn == pnum) {
[c3f7d37]138 log_msg(LOG_DEFAULT, LVL_DEBUG2, "port already used");
[8a637a4]139 return EEXIST;
[1ede059]140 }
[ab6326bc]141 }
142 }
143
144 p = calloc(1, sizeof(portrng_port_t));
145 if (p == NULL)
146 return ENOMEM;
147
148 p->pn = pnum;
[8d48c7e]149 p->arg = arg;
[ab6326bc]150 list_append(&p->lprng, &pr->used);
151 *apnum = pnum;
[c3f7d37]152 log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_alloc() - end OK pn=%" PRIu16,
[ab6326bc]153 pnum);
[2989c7e]154 return EOK;
155}
156
[b10460a]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 */
[b7fd2a0]165errno_t portrng_find_port(portrng_t *pr, uint16_t pnum, void **rarg)
[8d48c7e]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
[b10460a]177/** Free port in port range.
178 *
179 * @param pr Port range
180 * @param pnum Port number
181 */
[ab6326bc]182void portrng_free_port(portrng_t *pr, uint16_t pnum)
[2989c7e]183{
[e1b4ae0]184 log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_free_port(%u)", pnum);
[c3f7d37]185 log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_free_port() - begin");
[ab6326bc]186 list_foreach(pr->used, lprng, portrng_port_t, port) {
[e1b4ae0]187 log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_free_port - check port %u", port->pn);
[ab6326bc]188 if (port->pn == pnum) {
[e1b4ae0]189 log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_free_port - OK");
[ab6326bc]190 list_remove(&port->lprng);
191 free(port);
[e1b4ae0]192 log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_free_port() - end");
[ab6326bc]193 return;
194 }
195 }
196
[e1b4ae0]197 log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_free_port - FAIL");
[ab6326bc]198 assert(false);
[2989c7e]199}
200
[b10460a]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 */
[ab6326bc]206bool portrng_empty(portrng_t *pr)
[2989c7e]207{
[c3f7d37]208 log_msg(LOG_DEFAULT, LVL_DEBUG2, "portrng_empty()");
[ab6326bc]209 return list_empty(&pr->used);
[2989c7e]210}
211
212/**
213 * @}
[4794417]214 */
Note: See TracBrowser for help on using the repository browser.