You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

snsd_cache.c 26KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217
  1. /* This file is part of Netsukuku
  2. * (c) Copyright 2006 Andrea Lo Pumo aka AlpT <alpt@freaknet.org>
  3. *
  4. * This source code is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as published
  6. * by the Free Software Foundation; either version 2 of the License,
  7. * or (at your option) any later version.
  8. *
  9. * This source code is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. * Please refer to the GNU Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Public License along with
  15. * this source code; if not, write to:
  16. * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. *
  18. * --
  19. * snsd.c
  20. *
  21. * Scattered Name Service Digregation
  22. *
  23. * Here there are the main functions used to add/modify/delete/pack/unpack
  24. * the records in the SNSD linked lists.
  25. * The functions which handle SNSD requests/replies are in andna.c.
  26. */
  27. #include "includes.h"
  28. #include "snsd_cache.h"
  29. #include "common.h"
  30. int net_family;
  31. void
  32. snsd_cache_init(int family)
  33. {
  34. net_family = family;
  35. }
  36. /*
  37. * str_to_snsd_proto
  38. *
  39. * It returns the protocol number associated to `proto_name'.
  40. * (See the `proto_str' static array in snsd.h)
  41. *
  42. * If no protocol matched, 0 is returned.
  43. */
  44. u_char
  45. str_to_snsd_proto(char *proto_name)
  46. {
  47. int i;
  48. for (i = 0; i <= 256; i++) {
  49. if (!proto_str[i])
  50. break;
  51. if (!strcmp(proto_name, proto_str[i]))
  52. return i + 1;
  53. }
  54. return 0;
  55. }
  56. const char *
  57. snsd_proto_to_str(u_char proto)
  58. {
  59. return proto_str[proto - 1];
  60. }
  61. /*
  62. * str_to_snsd_service
  63. *
  64. * `str' is a string which specifies the service of a snsd record. It
  65. * is one of the service listed in /etc/services. It can be expressed
  66. * also in numeric form.
  67. * It is also possible to specify the protocol, f.e:
  68. * "domain", "53", "53/udp", "domain/udp"
  69. * are valid service strings.
  70. *
  71. * This function converts `str' to a service number and a protocol
  72. * number in the str_to_snsd_proto() format.
  73. *
  74. * On error a negative value is returned.
  75. * If the service is invalid -1 is returned.
  76. * If the protocol is invalid -2 is returned.
  77. */
  78. int
  79. str_to_snsd_service(char *str, int *service, u_char * proto)
  80. {
  81. struct servent *st;
  82. char *servname, *servproto;
  83. servname = str;
  84. if ((servproto = strchr(str, '/'))) {
  85. *servproto = 0;
  86. servproto++;
  87. if (!(*proto = str_to_snsd_proto(servproto)))
  88. return -1;
  89. } else
  90. *proto = SNSD_DEFAULT_PROTO;
  91. if (!isdigit(servname[0])) {
  92. if (!(st = getservbyname(servname, 0)))
  93. return -2;
  94. *service = ntohs(st->s_port);
  95. } else
  96. *service = atoi(servname);
  97. return 0;
  98. }
  99. /*
  100. * snsd_service_to_str
  101. *
  102. * Converts the `service' and `proto' numbers to a servent struct, and sets
  103. * the pointer `service_str' to the service string while `proto_str' to the
  104. * protocol string.
  105. * A pointer to the servent structure is returned.
  106. *
  107. * On error 0 is returned.
  108. */
  109. struct servent *
  110. snsd_service_to_str(int service, u_char proto, char **service_str,
  111. char **proto_str)
  112. {
  113. struct servent *st = 0;
  114. if (!(st = getservbyport(service, snsd_proto_to_str(proto))))
  115. return 0;
  116. *service_str = st->s_name;
  117. *proto_str = st->s_proto;
  118. return st;
  119. }
  120. /*\
  121. *
  122. * * * SNSD structs functions * * *
  123. *
  124. \*/
  125. snsd_service *
  126. snsd_find_service(snsd_service * sns, u_short service, u_char proto)
  127. {
  128. list_for(sns)
  129. if (sns->service == service &&
  130. (sns->proto == proto || service == SNSD_DEFAULT_SERVICE))
  131. return sns;
  132. return 0;
  133. }
  134. snsd_service *
  135. snsd_add_service(snsd_service ** head, u_short service, u_char proto)
  136. {
  137. snsd_service *sns, *new;
  138. if ((sns = snsd_find_service(*head, service, proto)))
  139. return sns;
  140. new = xzalloc(sizeof(snsd_service));
  141. new->service = service;
  142. new->proto = proto;
  143. *head = list_add(*head, new);
  144. return new;
  145. }
  146. snsd_prio *
  147. snsd_find_prio(snsd_prio * snp, u_char prio)
  148. {
  149. list_for(snp)
  150. if (snp->prio == prio)
  151. return snp;
  152. return 0;
  153. }
  154. snsd_prio *
  155. snsd_add_prio(snsd_prio ** head, u_char prio)
  156. {
  157. snsd_prio *snp, *new;
  158. if ((snp = snsd_find_prio(*head, prio)))
  159. return snp;
  160. new = xzalloc(sizeof(snsd_prio));
  161. new->prio = prio;
  162. *head = list_add(*head, new);
  163. return new;
  164. }
  165. snsd_node *
  166. snsd_find_node_by_record(snsd_node * snd, uintptr_t record[MAX_IP_INT])
  167. {
  168. list_for(snd)
  169. if (!memcmp(snd->record, record, MAX_IP_SZ))
  170. return snd;
  171. return 0;
  172. }
  173. /*
  174. * snsd_add_node
  175. *
  176. * If `record' is not NULL, it searches for a snsd_node struct which has
  177. * the same `record' of the argument. If it is found, it is returned.
  178. * If it isn't found or `record' is NULL, it adds a new snsd_node struct
  179. * in the `*head' llist and returns it.
  180. * `max_records' is the max number of records allowed in the llist. If no
  181. * empty place are left to add the new struct, 0 is returned.
  182. */
  183. snsd_node *
  184. snsd_add_node(snsd_node ** head, u_short * counter,
  185. u_short max_records, uintptr_t record[MAX_IP_INT])
  186. {
  187. snsd_node *snd;
  188. if (record && (snd = snsd_find_node_by_record(*head, record)))
  189. return snd;
  190. if (*counter >= max_records)
  191. /* The llist is full */
  192. return 0;
  193. snd = xzalloc(sizeof(snsd_node));
  194. if (record)
  195. memcpy(snd->record, record, MAX_IP_SZ);
  196. clist_add(head, counter, snd);
  197. return snd;
  198. }
  199. /*
  200. * snsd_add_first_node
  201. *
  202. * It adds a new node in the llist if `*head' or `*counter' is zero.
  203. * The new node is returned.
  204. * If it isn't zero, it returns the first struct of the llist.
  205. */
  206. snsd_node *
  207. snsd_add_first_node(snsd_node ** head, u_short * counter,
  208. u_short max_records, uintptr_t record[MAX_IP_INT])
  209. {
  210. if (!(*head) || !(*counter))
  211. return snsd_add_node(head, counter, max_records, record);
  212. return *head;
  213. }
  214. /*
  215. * just a wrapper
  216. */
  217. snsd_node *
  218. snsd_add_mainip(snsd_service ** head, u_short * counter,
  219. u_short max_records, uintptr_t record[MAX_IP_INT])
  220. {
  221. snsd_service *sns;
  222. snsd_prio *snp;
  223. snsd_node *snd;
  224. if (!(sns = snsd_add_service(head, SNSD_DEFAULT_SERVICE,
  225. SNSD_DEFAULT_PROTO)) ||
  226. !(snp = snsd_add_prio(&sns->prio,
  227. SNSD_DEFAULT_PRIO)) ||
  228. !(snd = snsd_add_node(&snp->node, counter, max_records, record)))
  229. return 0;
  230. snd->flags |= SNSD_NODE_IP | SNSD_NODE_MAIN_IP;
  231. snd->weight = SNSD_DEFAULT_WEIGHT;
  232. return snd;
  233. }
  234. /*\
  235. *
  236. * * * * Destroyer functions * * *
  237. *
  238. \*/
  239. void
  240. snsd_node_llist_del(snsd_node ** head, u_short * counter)
  241. {
  242. clist_destroy(head, counter);
  243. }
  244. void
  245. snsd_prio_llist_del(snsd_prio ** head)
  246. {
  247. snsd_prio *snp = (*head);
  248. u_short counter;
  249. list_for(snp)
  250. snsd_node_llist_del(&snp->node, &counter);
  251. clist_destroy(head, &counter);
  252. (*head) = (snsd_prio *) clist_init(&counter);
  253. }
  254. void
  255. snsd_service_llist_del(snsd_service ** head)
  256. {
  257. snsd_service *sns = (*head);
  258. int counter;
  259. list_for(sns)
  260. snsd_prio_llist_del(&sns->prio);
  261. clist_destroy(head, &counter);
  262. }
  263. /*
  264. * snsd_record_del_selected
  265. *
  266. * It deletes from the `*head' llist all the snsd records
  267. * which are found in the `selected' llist. In other words, if a snsd record
  268. * present in the `selected' llist is found `*head', it is removed from
  269. * `*head'.
  270. * `snsd_counter' is the record counter of `*head'.
  271. */
  272. void
  273. snsd_record_del_selected(snsd_service ** head, u_short * snd_counter,
  274. snsd_service * selected)
  275. {
  276. snsd_service *sns;
  277. snsd_prio *snp, *snp_sel;
  278. snsd_node *snd, *snd_sel;
  279. list_for(selected) {
  280. sns = snsd_find_service(*head, selected->service, selected->proto);
  281. if (!sns)
  282. continue;
  283. snp_sel = selected->prio;
  284. list_for(snp_sel) {
  285. if (!(snp = snsd_find_prio(sns->prio, snp_sel->prio)))
  286. continue;
  287. snd_sel = snp_sel->node;
  288. list_for(snd_sel) {
  289. while ((snd = snsd_find_node_by_record(snp->node,
  290. snd_sel->record))) {
  291. /*
  292. * there can be multiple nodes with the same
  293. * record, delete them all with this
  294. * `while'.
  295. */
  296. clist_del(&snp->node, snd_counter, snd);
  297. }
  298. }
  299. if (!snp->node)
  300. /* if we emptied the snp->node llist, delete
  301. * this prio struct too */
  302. sns->prio = list_del(sns->prio, snp);
  303. }
  304. if (!sns->prio)
  305. /* if we emptied the sns->prio llist, delete
  306. * this service struct too */
  307. *head = list_del((*head), sns);
  308. }
  309. }
  310. /*\
  311. *
  312. * * * * Pack/Unpack functions * * *
  313. *
  314. \*/
  315. /*
  316. * snsd_pack_node
  317. *
  318. * It packs the `node' snsd_node struct. The package is written in `pack'.
  319. * `free_sz' is the number of free bytes of `pack'. If `free_sz' is less than
  320. * SNSD_NODE_PACK_SZ, -1 is returned.
  321. * The number of bytes written in `pack' is returned.
  322. */
  323. int
  324. snsd_pack_node(char *pack, size_t free_sz, snsd_node * node)
  325. {
  326. char *buf = pack;
  327. if (free_sz < SNSD_NODE_PACK_SZ)
  328. return -1;
  329. memcpy(buf, node->record, MAX_IP_SZ);
  330. if (node->flags & SNSD_NODE_IP)
  331. inet_htonl((u_int *) buf, net_family);
  332. buf += MAX_IP_SZ;
  333. memcpy(buf, &node->flags, sizeof(char));
  334. buf += sizeof(char);
  335. memcpy(buf, &node->weight, sizeof(char));
  336. buf += sizeof(char);
  337. return SNSD_NODE_PACK_SZ;
  338. }
  339. /*
  340. * snsd_unpack_node
  341. *
  342. * It returns the unpacked snsd_node struct.
  343. * `pack' is the buffer which contains the packed struct.
  344. *
  345. * We are assuming that the total size of the package is >= SNSD_NODE_PACK_SZ.
  346. */
  347. snsd_node *
  348. snsd_unpack_node(char *pack)
  349. {
  350. snsd_node *snd;
  351. char *buf;
  352. snd = xzalloc(sizeof(snsd_node));
  353. buf = pack;
  354. memcpy(snd->record, buf, MAX_IP_SZ);
  355. buf += MAX_IP_SZ;
  356. memcpy(&snd->flags, buf, sizeof(char));
  357. buf += sizeof(char);
  358. snd->weight = SNSD_WEIGHT((*((char *) (buf))));
  359. buf += sizeof(char);
  360. if (snd->flags & SNSD_NODE_IP)
  361. inet_ntohl((u_int*)snd->record, net_family);
  362. return snd;
  363. }
  364. /*
  365. * snsd_pack_all_nodes
  366. *
  367. * It packs all the snsd_node structs present in the `head' linked list.
  368. * The pack is written in `pack' which has to have enough space to contain the
  369. * packed llist. The size of the llist can be calculate using:
  370. * SNSD_NODE_LLIST_PACK_SZ(head)
  371. *
  372. * `pack_sz' is the number of free bytes allocated in `pack'.
  373. *
  374. * The number of bytes written in `pack' is returned.
  375. *
  376. * On error -1 is returned.
  377. */
  378. int
  379. snsd_pack_all_nodes(char *pack, size_t pack_sz, snsd_node * head)
  380. {
  381. struct snsd_node_llist_hdr *hdr;
  382. snsd_node *snd = head;
  383. int sz = 0, wsz = 0, counter = 0;
  384. hdr = (struct snsd_node_llist_hdr *) pack;
  385. pack += sizeof(struct snsd_node_llist_hdr);
  386. wsz += sizeof(struct snsd_node_llist_hdr);
  387. list_for(snd) {
  388. sz = snsd_pack_node(pack, pack_sz - wsz, snd);
  389. if (sz <= 0)
  390. return -1;
  391. wsz += sz;
  392. pack += sz;
  393. counter++;
  394. }
  395. hdr->count = htons(counter);
  396. return wsz;
  397. }
  398. /*
  399. * snsd_unpack_all_nodes
  400. *
  401. * It unpacks a packed linked list of snsd_nodes, which is pointed by `pack'.
  402. * The number of unpacked structs is written in `nodes_counter'.
  403. *
  404. * `*unpacked_sz' is incremented by the number of unpacked bytes.
  405. *
  406. * The head of the unpacked llist is returned.
  407. * On error 0 is returned.
  408. */
  409. snsd_node *
  410. snsd_unpack_all_nodes(char *pack, size_t pack_sz,
  411. size_t * unpacked_sz, u_short * nodes_counter)
  412. {
  413. snsd_node *snd_head = 0, *snd;
  414. char *buf = pack;
  415. int i, sz = 0;
  416. u_short counter;
  417. if ((sz += sizeof(struct snsd_node_llist_hdr)) > pack_sz)
  418. ERROR_FINISH(snd_head, 0, finish);
  419. counter = ntohs((*(short *) buf));
  420. buf += sizeof(short);
  421. if (counter > SNSD_MAX_REC_SERV)
  422. ERROR_FINISH(snd_head, 0, finish);
  423. *nodes_counter = 0;
  424. for (i = 0; i < counter; i++) {
  425. if ((sz += SNSD_NODE_PACK_SZ) > pack_sz)
  426. ERROR_FINISH(snd_head, 0, finish);
  427. snd = snsd_unpack_node(buf);
  428. buf += SNSD_NODE_PACK_SZ;
  429. clist_add(&snd_head, nodes_counter, snd);
  430. }
  431. finish:
  432. (*unpacked_sz) += sz;
  433. return snd_head;
  434. }
  435. /*
  436. * snsd_pack_prio
  437. *
  438. * It packs the `prio' snsd_prio struct in the `pack' buffer, which has
  439. * `free_sz' bytes allocated.
  440. * In the packs it includes the `prio'->node llist too.
  441. *
  442. * On error -1 is returned, otherwise the size of the package is returned.
  443. */
  444. int
  445. snsd_pack_prio(char *pack, size_t free_sz, snsd_prio * prio)
  446. {
  447. char *buf = pack;
  448. int wsz = 0, sz = 0;
  449. if (free_sz < SNSD_PRIO_PACK_SZ)
  450. return -1;
  451. *buf = prio->prio;
  452. buf += sizeof(char);
  453. wsz += sizeof(char);
  454. sz = snsd_pack_all_nodes(buf, free_sz - wsz, prio->node);
  455. if (sz <= 0)
  456. return -1;
  457. wsz += sz;
  458. return wsz;
  459. }
  460. /*
  461. * snsd_unpack_prio
  462. *
  463. * It unpacks a packed snsd_prio struct and returns it.
  464. * `pack' is the package, which is `pack_sz' big.
  465. *
  466. * The number of unpacked snsd_node structs is written in `nodes_counter'.
  467. *
  468. * `*unpacked_sz' is incremented by the number of unpacked bytes.
  469. *
  470. * On error 0 is returned
  471. */
  472. snsd_prio *
  473. snsd_unpack_prio(char *pack, size_t pack_sz, size_t * unpacked_sz,
  474. u_short * nodes_counter)
  475. {
  476. snsd_prio *snp;
  477. u_short counter = 0;
  478. *nodes_counter = counter;
  479. snp = xzalloc(sizeof(snsd_prio));
  480. snp->prio = *pack;
  481. pack += sizeof(char);
  482. (*unpacked_sz) += sizeof(char);
  483. snp->node =
  484. snsd_unpack_all_nodes(pack, pack_sz - sizeof(char), unpacked_sz,
  485. &counter);
  486. if (!snp->node || counter > SNSD_MAX_REC_SERV)
  487. return 0;
  488. *nodes_counter = counter;
  489. return snp;
  490. }
  491. /*
  492. * snsd_pack_all_prios
  493. *
  494. * It packs the whole snsd_prio linked list whose head is `head'.
  495. * `pack' is the buffer where the package will be stored.
  496. * `pack' is `pack_sz' bytes big.
  497. * Use SNSD_PRIO_LLIST_PACK_SZ(head) to calculate the pack size.
  498. *
  499. * The number of bytes stored in `pack' is returned.
  500. *
  501. * On error -1 is returned.
  502. */
  503. int
  504. snsd_pack_all_prios(char *pack, size_t pack_sz, snsd_prio * head)
  505. {
  506. struct snsd_prio_llist_hdr *hdr;
  507. snsd_prio *snp = head;
  508. int sz = 0, wsz = 0, counter = 0;
  509. hdr = (struct snsd_prio_llist_hdr *) pack;
  510. pack += sizeof(struct snsd_prio_llist_hdr);
  511. wsz += sizeof(struct snsd_prio_llist_hdr);
  512. list_for(snp) {
  513. sz = snsd_pack_prio(pack, pack_sz - wsz, snp);
  514. if (sz <= 0)
  515. return -1;
  516. wsz += sz;
  517. pack += sz;
  518. counter++;
  519. }
  520. hdr->count = htons(counter);
  521. return wsz;
  522. }
  523. /*
  524. * snsd_unpack_all_prios
  525. *
  526. * It unpacks the packed snsd_prio llist.
  527. * The head of the newly allocated llist is returned.
  528. *
  529. * The number of unpacked snsd_node structs is written in `nodes_counter'.
  530. *
  531. * `*unpacked_sz' is incremented by the number of unpacked bytes.
  532. *
  533. * On error 0 is returned.
  534. */
  535. snsd_prio *
  536. snsd_unpack_all_prios(char *pack, size_t pack_sz,
  537. size_t * unpacked_sz, u_short * nodes_counter)
  538. {
  539. snsd_prio *snp_head = 0, *snp;
  540. char *buf = pack;
  541. u_short counter = 0, ncounter = 0, tmp_counter = 0;
  542. int i, sz = 0, tmp_sz, usz = 0;
  543. *nodes_counter = ncounter;
  544. if ((sz += sizeof(struct snsd_prio_llist_hdr)) > pack_sz)
  545. ERROR_FINISH(snp_head, 0, finish);
  546. counter = ntohs((*(short *) buf));
  547. buf += sizeof(short);
  548. usz += sizeof(short);
  549. (*unpacked_sz) += sizeof(short);
  550. if (counter > SNSD_MAX_REC_SERV || counter <= 0)
  551. ERROR_FINISH(snp_head, 0, finish);
  552. for (i = 0; i < counter; i++) {
  553. if ((sz += SNSD_PRIO_PACK_SZ) > pack_sz)
  554. ERROR_FINISH(snp_head, 0, finish);
  555. tmp_sz = (*unpacked_sz);
  556. snp = snsd_unpack_prio(buf, pack_sz - usz, unpacked_sz,
  557. &tmp_counter);
  558. ncounter += tmp_counter;
  559. if (!snp || ncounter > SNSD_MAX_REC_SERV)
  560. ERROR_FINISH(snp_head, 0, finish);
  561. /* tmp_sz=how much we've read so far from `buf' */
  562. tmp_sz = (*unpacked_sz) - tmp_sz;
  563. buf += tmp_sz;
  564. usz += tmp_sz;
  565. clist_add(&snp_head, &tmp_counter, snp);
  566. }
  567. finish:
  568. *nodes_counter = ncounter;
  569. return snp_head;
  570. }
  571. /*
  572. * snsd_pack_service
  573. *
  574. * It packs the `service' snsd_service struct in the `pack' buffer, which has
  575. * `free_sz' bytes allocated.
  576. * In the packs it includes the `service'->prio llist too.
  577. *
  578. * On error -1 is returned, otherwise the size of the package is returned.
  579. */
  580. int
  581. snsd_pack_service(char *pack, size_t free_sz, snsd_service * service)
  582. {
  583. char *buf = pack;
  584. int wsz = 0, sz = 0;
  585. if (!service || free_sz < SNSD_SERVICE_PACK_SZ)
  586. return -1;
  587. (*(u_short *) (buf)) = htons(service->service);
  588. buf += sizeof(short);
  589. (*(u_char *) (buf)) = service->proto;
  590. buf += sizeof(u_char);
  591. wsz += SNSD_SERVICE_PACK_SZ;
  592. sz = snsd_pack_all_prios(buf, free_sz - wsz, service->prio);
  593. if (sz <= 0)
  594. return -1;
  595. wsz += sz;
  596. return wsz;
  597. }
  598. /*
  599. * snsd_unpack_service
  600. *
  601. * It unpacks a packed snsd_service struct and returns it.
  602. * `pack' is the package, which is `pack_sz' big.
  603. *
  604. * The number of unpacked snsd_node structs is written in `nodes_counter'.
  605. *
  606. * `*unpacked_sz' is incremented by the number of unpacked bytes.
  607. *
  608. * On error 0 is returned
  609. */
  610. snsd_service *
  611. snsd_unpack_service(char *pack, size_t pack_sz,
  612. size_t * unpacked_sz, u_short * nodes_counter)
  613. {
  614. snsd_service *sns;
  615. u_short tmp_counter = 0, counter = 0;
  616. *nodes_counter = counter;
  617. sns = xzalloc(sizeof(snsd_service));
  618. sns->service = ntohs((*(u_short *) pack));
  619. pack += sizeof(short);
  620. sns->proto = (*(u_char *) pack);
  621. pack += sizeof(u_char);
  622. (*unpacked_sz) += SNSD_SERVICE_PACK_SZ;
  623. pack_sz -= SNSD_SERVICE_PACK_SZ;
  624. sns->prio = snsd_unpack_all_prios(pack, pack_sz, unpacked_sz,
  625. &tmp_counter);
  626. counter += tmp_counter;
  627. if (!sns->prio || counter > SNSD_MAX_REC_SERV)
  628. return 0;
  629. *nodes_counter = counter;
  630. return sns;
  631. }
  632. /*
  633. * snsd_pack_all_services
  634. *
  635. * It packs the whole snsd_service linked list whose head is `head'.
  636. * `pack' is the buffer where the package will be stored, it must have already
  637. * `pack_sz' bytes allocated.
  638. * Use SNSD_SERVICE_LLIST_PACK_SZ(head) to calculate the pack size.
  639. *
  640. * The number of bytes stored in `pack' is returned.
  641. *
  642. * On error -1 is returned.
  643. */
  644. int
  645. snsd_pack_all_services(char *pack, size_t pack_sz, snsd_service * head)
  646. {
  647. struct snsd_service_llist_hdr *hdr;
  648. snsd_service *sns = head;
  649. int sz = 0, wsz = 0, counter = 0;
  650. hdr = (struct snsd_service_llist_hdr *) pack;
  651. pack += sizeof(struct snsd_service_llist_hdr);
  652. wsz += sizeof(struct snsd_service_llist_hdr);
  653. list_for(sns) {
  654. sz = snsd_pack_service(pack, pack_sz - wsz, sns);
  655. if (sz <= 0)
  656. return -1;
  657. wsz += sz;
  658. pack += sz;
  659. counter++;
  660. }
  661. hdr->count = htons(counter);
  662. return wsz;
  663. }
  664. /*
  665. * snsd_unpack_all_service
  666. *
  667. * It unpacks the packed snsd_service llist.
  668. * The head of the newly allocated llist is returned.
  669. *
  670. * The number of unpacked snsd_node structs is written in `nodes_counter'.
  671. *
  672. * `*unpacked_sz' is incremented by the number of unpacked bytes.
  673. *
  674. * On error 0 is returned.
  675. */
  676. snsd_service *
  677. snsd_unpack_all_service(char *pack, size_t pack_sz,
  678. size_t * unpacked_sz, u_short * nodes_counter)
  679. {
  680. snsd_service *sns_head = 0, *sns = 0;
  681. char *buf = pack;
  682. u_short counter = 0, ncounter = 0, tmp_counter = 0;
  683. int i, sz = 0, tmp_sz, usz = 0;
  684. if (nodes_counter)
  685. *nodes_counter = ncounter;
  686. if ((sz += sizeof(struct snsd_service_llist_hdr)) > pack_sz)
  687. ERROR_FINISH(sns_head, 0, finish);
  688. counter = ntohs((*(short *) buf));
  689. buf += sizeof(short);
  690. usz += sizeof(short);
  691. (*unpacked_sz) += sizeof(short);
  692. if (counter > SNSD_MAX_RECORDS || counter <= 0)
  693. ERROR_FINISH(sns_head, 0, finish);
  694. for (i = 0; i < counter; i++) {
  695. if ((sz += SNSD_SERVICE_PACK_SZ) > pack_sz)
  696. ERROR_FINISH(sns_head, 0, finish);
  697. tmp_sz = (*unpacked_sz);
  698. sns = snsd_unpack_service(buf, pack_sz - usz, unpacked_sz,
  699. &tmp_counter);
  700. ncounter += tmp_counter;
  701. if (!sns || ncounter > SNSD_MAX_RECORDS)
  702. ERROR_FINISH(sns_head, 0, finish);
  703. /* tmp_sz=how much we've read from `buf' */
  704. tmp_sz = (*unpacked_sz) - tmp_sz;
  705. buf += tmp_sz;
  706. usz += tmp_sz;
  707. clist_add(&sns_head, &tmp_counter, sns);
  708. }
  709. finish:
  710. if (nodes_counter)
  711. *nodes_counter = ncounter;
  712. return sns_head;
  713. }
  714. /*\
  715. *
  716. * * * * Misc functions * * *
  717. *
  718. \*/
  719. int
  720. snsd_count_nodes(snsd_node * head)
  721. {
  722. return list_count(head);
  723. }
  724. int
  725. snsd_count_prio_nodes(snsd_prio * head)
  726. {
  727. int count = 0;
  728. list_for(head)
  729. count += snsd_count_nodes(head->node);
  730. return count;
  731. }
  732. int
  733. snsd_count_service_nodes(snsd_service * head)
  734. {
  735. int count = 0;
  736. list_for(head)
  737. count += snsd_count_prio_nodes(head->prio);
  738. return count;
  739. }
  740. /*
  741. * snsd_choose_wrand
  742. *
  743. * It returns a snsd_node of the `head' llist. The snsd_node is chosen
  744. * randomly. The weight of a node is proportional to its probability of being
  745. * picked.
  746. * On error (no nodes?) 0 is returned.
  747. */
  748. snsd_node *
  749. snsd_choose_wrand(snsd_node * head)
  750. {
  751. snsd_node *snd = head;
  752. int tot_w = 0, r = 0, nmemb = 0;
  753. nmemb = list_count(snd);
  754. list_for(snd)
  755. tot_w += snd->weight;
  756. if (!tot_w)
  757. return list_pos(snd, rand_range(0, nmemb - 1));
  758. r = rand_range(1, tot_w);
  759. tot_w = 0;
  760. snd = head;
  761. list_for(snd) {
  762. if (r > tot_w && (r <= tot_w + snd->weight))
  763. return snd;
  764. tot_w += snd->weight;
  765. }
  766. return 0;
  767. }
  768. /*
  769. * snsd_highest_prio
  770. *
  771. * It returns the snsd_prio struct which has the highest `prio' value.
  772. */
  773. snsd_prio *
  774. snsd_highest_prio(snsd_prio * head)
  775. {
  776. snsd_prio *highest = head;
  777. list_for(head)
  778. if (head->prio > highest->prio)
  779. highest = head;
  780. return highest;
  781. }
  782. /*
  783. * snsd_find_mainip
  784. *
  785. * It searches through the whole `sns' llist a snsd_node which has the
  786. * SNSD_NODE_MAIN_IP flag set.
  787. *
  788. * If it is found, it returns a pointer to it, otherwise 0 it returned.
  789. */
  790. snsd_node *
  791. snsd_find_mainip(snsd_service * sns)
  792. {
  793. snsd_prio *snp;
  794. snsd_node *snd;
  795. list_for(sns) {
  796. snp = sns->prio;
  797. list_for(snp) {
  798. snd = snp->node;
  799. list_for(snd)
  800. if (snd->flags & SNSD_NODE_MAIN_IP)
  801. return snd;
  802. }
  803. }
  804. return 0;
  805. }
  806. /*
  807. * snsd_unset_all_flags
  808. *
  809. * It unset the given `flag' in all the snsd records of the `sns' llist.
  810. */
  811. void
  812. snsd_unset_all_flags(snsd_service * sns, u_char flag)
  813. {
  814. snsd_prio *snp;
  815. snsd_node *snd;
  816. list_for(sns) {
  817. snp = sns->prio;
  818. list_for(snp) {
  819. snd = snp->node;
  820. list_for(snd)
  821. snd->flags &= ~flag;
  822. }
  823. }
  824. return;
  825. }
  826. /*\
  827. *
  828. * * * * Linked list copy functions * * *
  829. *
  830. \*/
  831. /*
  832. * snsd_node_llist_copy
  833. *
  834. * It duplicates an entire snsd_node llist in a new mallocated space.
  835. * The other sub-llist are duplicated too.
  836. * The head of the new llist is returned.
  837. */
  838. snsd_node *
  839. snsd_node_llist_copy(snsd_node * snd)
  840. {
  841. snsd_node *new_snd = 0;
  842. snd = new_snd = list_copy_all(snd);
  843. list_for(snd)
  844. if (snd->pubkey)
  845. snd->pubkey = RSAPublicKey_dup(snd->pubkey);
  846. return new_snd;
  847. }
  848. /*
  849. * snsd_prio_llist_copy
  850. *
  851. * It duplicates an entire snsd_prio llist in a new mallocated space.
  852. * The other sub-llist are duplicated too.
  853. * The head of the new llist is returned.
  854. */
  855. snsd_prio *
  856. snsd_prio_llist_copy(snsd_prio * snp)
  857. {
  858. snsd_prio *new_snp = 0;
  859. snp = new_snp = list_copy_all(snp);
  860. list_for(snp)
  861. snp->node = snsd_node_llist_copy(snp->node);
  862. return new_snp;
  863. }
  864. int
  865. is_equal_to_serv_proto(snsd_service * sns, u_short service, u_char proto)
  866. {
  867. return sns->service == service &&
  868. (sns->proto == proto || sns->service == SNSD_DEFAULT_SERVICE);
  869. }
  870. /*
  871. * snsd_service_llist_copy
  872. *
  873. * If `service' is equal to -1, it duplicates an entire snsd_service llist
  874. * in a new mallocated space, otherwise it duplicates only the snsd_service
  875. * structures which have the same service and proto values of `service' and
  876. * `proto'.
  877. * The other sub-llist are duplicated too.
  878. *
  879. * The head of the new llist is returned.
  880. * If nothing has been duplicated, 0 is returned.
  881. */
  882. snsd_service *
  883. snsd_service_llist_copy(snsd_service * sns, int service, u_char proto)
  884. {
  885. snsd_service *new_sns = 0;
  886. u_short short_service = (u_short) service;
  887. if (!sns)
  888. return 0;
  889. if (service == -1)
  890. sns = new_sns = list_copy_all(sns);
  891. else
  892. sns = new_sns = list_copy_some(sns, is_equal_to_serv_proto,
  893. short_service, proto);
  894. list_for(sns)
  895. sns->prio = snsd_prio_llist_copy(sns->prio);
  896. return new_sns;
  897. }
  898. /*\
  899. *
  900. * * * * Linked list merging functions * * *
  901. *
  902. * For an explanation of these things,
  903. * read snsd_service_llist_merge()
  904. \*/
  905. void
  906. snsd_merge_node(snsd_node ** head, u_short * snsd_counter, snsd_node * new)
  907. {
  908. snsd_node *snd;
  909. if (!(snd = snsd_find_node_by_record(*head, new->record))) {
  910. clist_add(head, snsd_counter, new);
  911. return;
  912. }
  913. list_copy(snd, new);
  914. }
  915. void
  916. snsd_node_llist_merge(snsd_node ** dst, u_short * snsd_counter,
  917. snsd_node * src)
  918. {
  919. list_for(src)
  920. snsd_merge_node(dst, snsd_counter, src);
  921. }
  922. void
  923. snsd_merge_prio(snsd_prio ** head, u_short * snsd_counter, snsd_prio * new)
  924. {
  925. snsd_prio *snp;
  926. if (!(snp = snsd_find_prio(*head, new->prio))) {
  927. *head = list_add(*head, new);
  928. return;
  929. }
  930. snsd_node_llist_merge(&snp->node, snsd_counter, new->node);
  931. }
  932. void
  933. snsd_prio_llist_merge(snsd_prio ** dst, u_short * snsd_counter,
  934. snsd_prio * src)
  935. {
  936. list_for(src)
  937. snsd_merge_prio(dst, snsd_counter, src);
  938. }
  939. void
  940. snsd_merge_service(snsd_service ** head, u_short * snsd_counter,
  941. snsd_service * new)
  942. {
  943. snsd_service *sns;
  944. if (!(sns = snsd_find_service(*head, new->service, new->proto))) {
  945. /* `new' doesn't exists in `head'. Add it. */
  946. *head = list_add(*head, new);
  947. return;
  948. }
  949. snsd_prio_llist_merge(&sns->prio, snsd_counter, new->prio);
  950. }
  951. /*
  952. * snsd_service_llist_merge
  953. *
  954. * It merges the `*dst' and `src' linked lists into a unique list, which
  955. * contains all the common elements between `*dst' and `src'.
  956. * In other words it is the result of the AND of the `*dst' and `src' sets.
  957. *
  958. * The result is written in the `*dst' llist itself and no memory is
  959. * allocated, thus if you don't want to modify `*dst', you have to do a copy
  960. * first using snsd_service_llist_copy().
  961. */
  962. void
  963. snsd_service_llist_merge(snsd_service ** dst, u_short * snsd_counter,
  964. snsd_service * src)
  965. {
  966. list_for(src)
  967. snsd_merge_service(dst, snsd_counter, src);
  968. }
  969. /*\
  970. *
  971. * * * * Dump functions * * *
  972. * (that don't stink)
  973. \*/
  974. void
  975. snsd_dump_node(snsd_node * snd, int single)
  976. {
  977. list_for(snd) {
  978. printf("\t\t{\n "
  979. "\t\trecord = %lx:%lx:%lx:%lx\n "
  980. "\t\tpubkey = %p\n "
  981. "\t\tflags = %d\n "
  982. "\t\tweight = %d\n",
  983. snd->record[0], snd->record[1],
  984. snd->record[2], snd->record[3],
  985. (char *) snd->pubkey, (int) snd->flags, (int) snd->weight);
  986. if (single)
  987. goto finish;
  988. }
  989. finish:
  990. printf("\t\t}\n");
  991. return;
  992. }
  993. void
  994. snsd_dump_prio(snsd_prio * snp, int single, int level)
  995. {
  996. list_for(snp) {
  997. printf("\t{\n \tprio = %d\n", snp->prio);
  998. snsd_dump_node(snp->node, !(level > 2));
  999. printf("\t}\n");
  1000. if (single)
  1001. goto finish;
  1002. }
  1003. finish:
  1004. printf("\t}\n");
  1005. return;
  1006. }
  1007. void
  1008. snsd_dump_service(snsd_service * sns, int single, int level)
  1009. {
  1010. list_for(sns) {
  1011. printf("{\n service = %d\n proto = %d\n",
  1012. sns->service, sns->proto);
  1013. snsd_dump_prio(sns->prio, !(level > 1), level);
  1014. printf("}\n");
  1015. if (single)
  1016. goto finish;
  1017. }
  1018. finish:
  1019. printf("}\n");
  1020. return;
  1021. }