libpfctl.c 83 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899
  1. /*-
  2. * SPDX-License-Identifier: BSD-2-Clause
  3. *
  4. * Copyright (c) 2021 Rubicon Communications, LLC (Netgate)
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * - Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * - Redistributions in binary form must reproduce the above
  14. * copyright notice, this list of conditions and the following
  15. * disclaimer in the documentation and/or other materials provided
  16. * with the distribution.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  21. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  22. * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  23. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  24. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  26. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  27. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  28. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  29. * POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. #include <sys/cdefs.h>
  32. #include <sys/ioctl.h>
  33. #include <sys/nv.h>
  34. #include <sys/queue.h>
  35. #include <sys/types.h>
  36. #include <net/if.h>
  37. #include <net/pfvar.h>
  38. #include <netinet/in.h>
  39. #include <netpfil/pf/pf_nl.h>
  40. #include <netlink/netlink.h>
  41. #include <netlink/netlink_generic.h>
  42. #include <netlink/netlink_snl.h>
  43. #include <netlink/netlink_snl_generic.h>
  44. #include <netlink/netlink_snl_route.h>
  45. #include <assert.h>
  46. #include <err.h>
  47. #include <errno.h>
  48. #include <fcntl.h>
  49. #include <stdlib.h>
  50. #include <string.h>
  51. #include "libpfctl.h"
  52. struct pfctl_handle {
  53. int fd;
  54. struct snl_state ss;
  55. };
  56. const char* PFCTL_SYNCOOKIES_MODE_NAMES[] = {
  57. "never",
  58. "always",
  59. "adaptive"
  60. };
  61. static int _pfctl_clear_states(int , const struct pfctl_kill *,
  62. unsigned int *, uint64_t);
  63. struct pfctl_handle *
  64. pfctl_open(const char *pf_device)
  65. {
  66. struct pfctl_handle *h;
  67. h = calloc(1, sizeof(struct pfctl_handle));
  68. h->fd = -1;
  69. h->fd = open(pf_device, O_RDWR);
  70. if (h->fd < 0)
  71. goto error;
  72. if (!snl_init(&h->ss, NETLINK_GENERIC))
  73. goto error;
  74. return (h);
  75. error:
  76. close(h->fd);
  77. snl_free(&h->ss);
  78. free(h);
  79. return (NULL);
  80. }
  81. void
  82. pfctl_close(struct pfctl_handle *h)
  83. {
  84. close(h->fd);
  85. snl_free(&h->ss);
  86. free(h);
  87. }
  88. int
  89. pfctl_fd(struct pfctl_handle *h)
  90. {
  91. return (h->fd);
  92. }
  93. static int
  94. pfctl_do_netlink_cmd(struct pfctl_handle *h, uint cmd)
  95. {
  96. struct snl_errmsg_data e = {};
  97. struct snl_writer nw;
  98. struct nlmsghdr *hdr;
  99. uint32_t seq_id;
  100. int family_id;
  101. family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME);
  102. if (family_id == 0)
  103. return (ENOTSUP);
  104. snl_init_writer(&h->ss, &nw);
  105. hdr = snl_create_genl_msg_request(&nw, family_id, cmd);
  106. hdr = snl_finalize_msg(&nw);
  107. if (hdr == NULL)
  108. return (ENOMEM);
  109. seq_id = hdr->nlmsg_seq;
  110. snl_send_message(&h->ss, hdr);
  111. while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
  112. }
  113. return (e.error);
  114. }
  115. static int
  116. pfctl_do_ioctl(int dev, uint cmd, size_t size, nvlist_t **nvl)
  117. {
  118. struct pfioc_nv nv;
  119. void *data;
  120. size_t nvlen;
  121. int ret;
  122. data = nvlist_pack(*nvl, &nvlen);
  123. if (nvlen > size)
  124. size = nvlen;
  125. retry:
  126. nv.data = malloc(size);
  127. if (nv.data == NULL) {
  128. ret = ENOMEM;
  129. goto out;
  130. }
  131. memcpy(nv.data, data, nvlen);
  132. nv.len = nvlen;
  133. nv.size = size;
  134. ret = ioctl(dev, cmd, &nv);
  135. if (ret == -1 && errno == ENOSPC) {
  136. size *= 2;
  137. free(nv.data);
  138. goto retry;
  139. }
  140. nvlist_destroy(*nvl);
  141. *nvl = NULL;
  142. if (ret == 0) {
  143. *nvl = nvlist_unpack(nv.data, nv.len, 0);
  144. if (*nvl == NULL) {
  145. ret = EIO;
  146. goto out;
  147. }
  148. } else {
  149. ret = errno;
  150. }
  151. out:
  152. free(data);
  153. free(nv.data);
  154. return (ret);
  155. }
  156. static void
  157. pf_nvuint_8_array(const nvlist_t *nvl, const char *name, size_t maxelems,
  158. uint8_t *numbers, size_t *nelems)
  159. {
  160. const uint64_t *tmp;
  161. size_t elems;
  162. tmp = nvlist_get_number_array(nvl, name, &elems);
  163. assert(elems <= maxelems);
  164. for (size_t i = 0; i < elems; i++)
  165. numbers[i] = tmp[i];
  166. if (nelems)
  167. *nelems = elems;
  168. }
  169. static void
  170. pf_nvuint_16_array(const nvlist_t *nvl, const char *name, size_t maxelems,
  171. uint16_t *numbers, size_t *nelems)
  172. {
  173. const uint64_t *tmp;
  174. size_t elems;
  175. tmp = nvlist_get_number_array(nvl, name, &elems);
  176. assert(elems <= maxelems);
  177. for (size_t i = 0; i < elems; i++)
  178. numbers[i] = tmp[i];
  179. if (nelems)
  180. *nelems = elems;
  181. }
  182. static void
  183. pf_nvuint_32_array(const nvlist_t *nvl, const char *name, size_t maxelems,
  184. uint32_t *numbers, size_t *nelems)
  185. {
  186. const uint64_t *tmp;
  187. size_t elems;
  188. tmp = nvlist_get_number_array(nvl, name, &elems);
  189. for (size_t i = 0; i < elems && i < maxelems; i++)
  190. numbers[i] = tmp[i];
  191. if (nelems)
  192. *nelems = elems;
  193. }
  194. static void
  195. pf_nvuint_64_array(const nvlist_t *nvl, const char *name, size_t maxelems,
  196. uint64_t *numbers, size_t *nelems)
  197. {
  198. const uint64_t *tmp;
  199. size_t elems;
  200. tmp = nvlist_get_number_array(nvl, name, &elems);
  201. assert(elems <= maxelems);
  202. for (size_t i = 0; i < elems; i++)
  203. numbers[i] = tmp[i];
  204. if (nelems)
  205. *nelems = elems;
  206. }
  207. int
  208. pfctl_startstop(struct pfctl_handle *h, int start)
  209. {
  210. return (pfctl_do_netlink_cmd(h, start ? PFNL_CMD_START : PFNL_CMD_STOP));
  211. }
  212. static void
  213. _pfctl_get_status_counters(const nvlist_t *nvl,
  214. struct pfctl_status_counters *counters)
  215. {
  216. const uint64_t *ids, *counts;
  217. const char *const *names;
  218. size_t id_len, counter_len, names_len;
  219. ids = nvlist_get_number_array(nvl, "ids", &id_len);
  220. counts = nvlist_get_number_array(nvl, "counters", &counter_len);
  221. names = nvlist_get_string_array(nvl, "names", &names_len);
  222. assert(id_len == counter_len);
  223. assert(counter_len == names_len);
  224. TAILQ_INIT(counters);
  225. for (size_t i = 0; i < id_len; i++) {
  226. struct pfctl_status_counter *c;
  227. c = malloc(sizeof(*c));
  228. if (c == NULL)
  229. continue;
  230. c->id = ids[i];
  231. c->counter = counts[i];
  232. c->name = strdup(names[i]);
  233. TAILQ_INSERT_TAIL(counters, c, entry);
  234. }
  235. }
  236. #define _OUT(_field) offsetof(struct pfctl_status_counter, _field)
  237. static const struct snl_attr_parser ap_counter[] = {
  238. { .type = PF_C_COUNTER, .off = _OUT(counter), .cb = snl_attr_get_uint64 },
  239. { .type = PF_C_NAME, .off = _OUT(name), .cb = snl_attr_get_string },
  240. { .type = PF_C_ID, .off = _OUT(id), .cb = snl_attr_get_uint32 },
  241. };
  242. SNL_DECLARE_ATTR_PARSER(counter_parser, ap_counter);
  243. #undef _OUT
  244. static bool
  245. snl_attr_get_counters(struct snl_state *ss, struct nlattr *nla,
  246. const void *arg __unused, void *target)
  247. {
  248. struct pfctl_status_counter counter = {};
  249. struct pfctl_status_counter *c;
  250. bool error;
  251. error = snl_parse_header(ss, NLA_DATA(nla), NLA_DATA_LEN(nla), &counter_parser, &counter);
  252. if (! error)
  253. return (error);
  254. c = malloc(sizeof(*c));
  255. if (c == NULL)
  256. return (false);
  257. c->id = counter.id;
  258. c->counter = counter.counter;
  259. c->name = strdup(counter.name);
  260. TAILQ_INSERT_TAIL((struct pfctl_status_counters *)target, c, entry);
  261. return (error);
  262. }
  263. struct snl_uint64_array {
  264. uint64_t *array;
  265. size_t count;
  266. size_t max;
  267. };
  268. static bool
  269. snl_attr_get_uint64_element(struct snl_state *ss, struct nlattr *nla,
  270. const void *arg, void *target)
  271. {
  272. bool error;
  273. uint64_t value;
  274. struct snl_uint64_array *t = (struct snl_uint64_array *)target;
  275. if (t->count >= t->max)
  276. return (false);
  277. error = snl_attr_get_uint64(ss, nla, arg, &value);
  278. if (! error)
  279. return (error);
  280. t->array[t->count++] = value;
  281. return (true);
  282. }
  283. static const struct snl_attr_parser ap_array[] = {
  284. { .cb = snl_attr_get_uint64_element },
  285. };
  286. SNL_DECLARE_ATTR_PARSER(array_parser, ap_array);
  287. static bool
  288. snl_attr_get_uint64_array(struct snl_state *ss, struct nlattr *nla,
  289. const void *arg, void *target)
  290. {
  291. struct snl_uint64_array a = {
  292. .array = target,
  293. .count = 0,
  294. .max = (size_t)arg,
  295. };
  296. bool error;
  297. error = snl_parse_header(ss, NLA_DATA(nla), NLA_DATA_LEN(nla), &array_parser, &a);
  298. if (! error)
  299. return (error);
  300. return (true);
  301. }
  302. #define _OUT(_field) offsetof(struct pfctl_status, _field)
  303. static const struct snl_attr_parser ap_getstatus[] = {
  304. { .type = PF_GS_IFNAME, .off = _OUT(ifname), .arg_u32 = IFNAMSIZ, .cb = snl_attr_copy_string },
  305. { .type = PF_GS_RUNNING, .off = _OUT(running), .cb = snl_attr_get_bool },
  306. { .type = PF_GS_SINCE, .off = _OUT(since), .cb = snl_attr_get_uint32 },
  307. { .type = PF_GS_DEBUG, .off = _OUT(debug), .cb = snl_attr_get_uint32 },
  308. { .type = PF_GS_HOSTID, .off = _OUT(hostid), .cb = snl_attr_get_uint32 },
  309. { .type = PF_GS_STATES, .off = _OUT(states), .cb = snl_attr_get_uint32 },
  310. { .type = PF_GS_SRC_NODES, .off = _OUT(src_nodes), .cb = snl_attr_get_uint32 },
  311. { .type = PF_GS_REASSEMBLE, .off = _OUT(reass), .cb = snl_attr_get_uint32 },
  312. { .type = PF_GS_SYNCOOKIES_ACTIVE, .off = _OUT(syncookies_active), .cb = snl_attr_get_uint32 },
  313. { .type = PF_GS_COUNTERS, .off = _OUT(counters), .cb = snl_attr_get_counters },
  314. { .type = PF_GS_LCOUNTERS, .off = _OUT(lcounters), .cb = snl_attr_get_counters },
  315. { .type = PF_GS_FCOUNTERS, .off = _OUT(fcounters), .cb = snl_attr_get_counters },
  316. { .type = PF_GS_SCOUNTERS, .off = _OUT(scounters), .cb = snl_attr_get_counters },
  317. { .type = PF_GS_CHKSUM, .off = _OUT(pf_chksum), .arg_u32 = PF_MD5_DIGEST_LENGTH, .cb = snl_attr_get_bytes },
  318. { .type = PF_GS_BCOUNTERS, .off = _OUT(bcounters), .arg_u32 = 2 * 2, .cb = snl_attr_get_uint64_array },
  319. { .type = PF_GS_PCOUNTERS, .off = _OUT(pcounters), .arg_u32 = 2 * 2 * 2, .cb = snl_attr_get_uint64_array },
  320. };
  321. static struct snl_field_parser fp_getstatus[] = {};
  322. SNL_DECLARE_PARSER(getstatus_parser, struct genlmsghdr, fp_getstatus, ap_getstatus);
  323. #undef _OUT
  324. struct pfctl_status *
  325. pfctl_get_status_h(struct pfctl_handle *h __unused)
  326. {
  327. struct pfctl_status *status;
  328. struct snl_errmsg_data e = {};
  329. struct nlmsghdr *hdr;
  330. struct snl_writer nw;
  331. uint32_t seq_id;
  332. int family_id;
  333. family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME);
  334. if (family_id == 0)
  335. return (NULL);
  336. snl_init_writer(&h->ss, &nw);
  337. hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GET_STATUS);
  338. hdr->nlmsg_flags |= NLM_F_DUMP;
  339. hdr = snl_finalize_msg(&nw);
  340. if (hdr == NULL) {
  341. return (NULL);
  342. }
  343. seq_id = hdr->nlmsg_seq;
  344. if (! snl_send_message(&h->ss, hdr))
  345. return (NULL);
  346. status = calloc(1, sizeof(*status));
  347. if (status == NULL)
  348. return (NULL);
  349. TAILQ_INIT(&status->counters);
  350. TAILQ_INIT(&status->lcounters);
  351. TAILQ_INIT(&status->fcounters);
  352. TAILQ_INIT(&status->scounters);
  353. while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
  354. if (! snl_parse_nlmsg(&h->ss, hdr, &getstatus_parser, status))
  355. continue;
  356. }
  357. return (status);
  358. }
  359. struct pfctl_status *
  360. pfctl_get_status(int dev)
  361. {
  362. struct pfctl_status *status;
  363. nvlist_t *nvl;
  364. size_t len;
  365. const void *chksum;
  366. status = calloc(1, sizeof(*status));
  367. if (status == NULL)
  368. return (NULL);
  369. nvl = nvlist_create(0);
  370. if (pfctl_do_ioctl(dev, DIOCGETSTATUSNV, 4096, &nvl)) {
  371. nvlist_destroy(nvl);
  372. free(status);
  373. return (NULL);
  374. }
  375. status->running = nvlist_get_bool(nvl, "running");
  376. status->since = nvlist_get_number(nvl, "since");
  377. status->debug = nvlist_get_number(nvl, "debug");
  378. status->hostid = ntohl(nvlist_get_number(nvl, "hostid"));
  379. status->states = nvlist_get_number(nvl, "states");
  380. status->src_nodes = nvlist_get_number(nvl, "src_nodes");
  381. status->syncookies_active = nvlist_get_bool(nvl, "syncookies_active");
  382. status->reass = nvlist_get_number(nvl, "reass");
  383. strlcpy(status->ifname, nvlist_get_string(nvl, "ifname"),
  384. IFNAMSIZ);
  385. chksum = nvlist_get_binary(nvl, "chksum", &len);
  386. assert(len == PF_MD5_DIGEST_LENGTH);
  387. memcpy(status->pf_chksum, chksum, len);
  388. _pfctl_get_status_counters(nvlist_get_nvlist(nvl, "counters"),
  389. &status->counters);
  390. _pfctl_get_status_counters(nvlist_get_nvlist(nvl, "lcounters"),
  391. &status->lcounters);
  392. _pfctl_get_status_counters(nvlist_get_nvlist(nvl, "fcounters"),
  393. &status->fcounters);
  394. _pfctl_get_status_counters(nvlist_get_nvlist(nvl, "scounters"),
  395. &status->scounters);
  396. pf_nvuint_64_array(nvl, "pcounters", 2 * 2 * 2,
  397. (uint64_t *)status->pcounters, NULL);
  398. pf_nvuint_64_array(nvl, "bcounters", 2 * 2,
  399. (uint64_t *)status->bcounters, NULL);
  400. nvlist_destroy(nvl);
  401. return (status);
  402. }
  403. int
  404. pfctl_clear_status(struct pfctl_handle *h)
  405. {
  406. return (pfctl_do_netlink_cmd(h, PFNL_CMD_CLEAR_STATUS));
  407. }
  408. static uint64_t
  409. _pfctl_status_counter(struct pfctl_status_counters *counters, uint64_t id)
  410. {
  411. struct pfctl_status_counter *c;
  412. TAILQ_FOREACH(c, counters, entry) {
  413. if (c->id == id)
  414. return (c->counter);
  415. }
  416. return (0);
  417. }
  418. uint64_t
  419. pfctl_status_counter(struct pfctl_status *status, int id)
  420. {
  421. return (_pfctl_status_counter(&status->counters, id));
  422. }
  423. uint64_t
  424. pfctl_status_lcounter(struct pfctl_status *status, int id)
  425. {
  426. return (_pfctl_status_counter(&status->lcounters, id));
  427. }
  428. uint64_t
  429. pfctl_status_fcounter(struct pfctl_status *status, int id)
  430. {
  431. return (_pfctl_status_counter(&status->fcounters, id));
  432. }
  433. uint64_t
  434. pfctl_status_scounter(struct pfctl_status *status, int id)
  435. {
  436. return (_pfctl_status_counter(&status->scounters, id));
  437. }
  438. void
  439. pfctl_free_status(struct pfctl_status *status)
  440. {
  441. struct pfctl_status_counter *c, *tmp;
  442. if (status == NULL)
  443. return;
  444. TAILQ_FOREACH_SAFE(c, &status->counters, entry, tmp) {
  445. free(c->name);
  446. free(c);
  447. }
  448. TAILQ_FOREACH_SAFE(c, &status->lcounters, entry, tmp) {
  449. free(c->name);
  450. free(c);
  451. }
  452. TAILQ_FOREACH_SAFE(c, &status->fcounters, entry, tmp) {
  453. free(c->name);
  454. free(c);
  455. }
  456. TAILQ_FOREACH_SAFE(c, &status->scounters, entry, tmp) {
  457. free(c->name);
  458. free(c);
  459. }
  460. free(status);
  461. }
  462. static void
  463. pfctl_nv_add_addr(nvlist_t *nvparent, const char *name,
  464. const struct pf_addr *addr)
  465. {
  466. nvlist_t *nvl = nvlist_create(0);
  467. nvlist_add_binary(nvl, "addr", addr, sizeof(*addr));
  468. nvlist_add_nvlist(nvparent, name, nvl);
  469. nvlist_destroy(nvl);
  470. }
  471. static void
  472. pf_nvaddr_to_addr(const nvlist_t *nvl, struct pf_addr *addr)
  473. {
  474. size_t len;
  475. const void *data;
  476. data = nvlist_get_binary(nvl, "addr", &len);
  477. assert(len == sizeof(struct pf_addr));
  478. memcpy(addr, data, len);
  479. }
  480. static void
  481. pfctl_nv_add_addr_wrap(nvlist_t *nvparent, const char *name,
  482. const struct pf_addr_wrap *addr)
  483. {
  484. nvlist_t *nvl = nvlist_create(0);
  485. nvlist_add_number(nvl, "type", addr->type);
  486. nvlist_add_number(nvl, "iflags", addr->iflags);
  487. if (addr->type == PF_ADDR_DYNIFTL)
  488. nvlist_add_string(nvl, "ifname", addr->v.ifname);
  489. if (addr->type == PF_ADDR_TABLE)
  490. nvlist_add_string(nvl, "tblname", addr->v.tblname);
  491. pfctl_nv_add_addr(nvl, "addr", &addr->v.a.addr);
  492. pfctl_nv_add_addr(nvl, "mask", &addr->v.a.mask);
  493. nvlist_add_nvlist(nvparent, name, nvl);
  494. nvlist_destroy(nvl);
  495. }
  496. static void
  497. pf_nvaddr_wrap_to_addr_wrap(const nvlist_t *nvl, struct pf_addr_wrap *addr)
  498. {
  499. bzero(addr, sizeof(*addr));
  500. addr->type = nvlist_get_number(nvl, "type");
  501. addr->iflags = nvlist_get_number(nvl, "iflags");
  502. if (addr->type == PF_ADDR_DYNIFTL) {
  503. strlcpy(addr->v.ifname, nvlist_get_string(nvl, "ifname"),
  504. IFNAMSIZ);
  505. addr->p.dyncnt = nvlist_get_number(nvl, "dyncnt");
  506. }
  507. if (addr->type == PF_ADDR_TABLE) {
  508. strlcpy(addr->v.tblname, nvlist_get_string(nvl, "tblname"),
  509. PF_TABLE_NAME_SIZE);
  510. addr->p.tblcnt = nvlist_get_number(nvl, "tblcnt");
  511. }
  512. pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "addr"), &addr->v.a.addr);
  513. pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "mask"), &addr->v.a.mask);
  514. }
  515. static void
  516. pfctl_nv_add_rule_addr(nvlist_t *nvparent, const char *name,
  517. const struct pf_rule_addr *addr)
  518. {
  519. uint64_t ports[2];
  520. nvlist_t *nvl = nvlist_create(0);
  521. pfctl_nv_add_addr_wrap(nvl, "addr", &addr->addr);
  522. ports[0] = addr->port[0];
  523. ports[1] = addr->port[1];
  524. nvlist_add_number_array(nvl, "port", ports, 2);
  525. nvlist_add_number(nvl, "neg", addr->neg);
  526. nvlist_add_number(nvl, "port_op", addr->port_op);
  527. nvlist_add_nvlist(nvparent, name, nvl);
  528. nvlist_destroy(nvl);
  529. }
  530. static void
  531. pf_nvrule_addr_to_rule_addr(const nvlist_t *nvl, struct pf_rule_addr *addr)
  532. {
  533. pf_nvaddr_wrap_to_addr_wrap(nvlist_get_nvlist(nvl, "addr"), &addr->addr);
  534. pf_nvuint_16_array(nvl, "port", 2, addr->port, NULL);
  535. addr->neg = nvlist_get_number(nvl, "neg");
  536. addr->port_op = nvlist_get_number(nvl, "port_op");
  537. }
  538. static void
  539. pf_nvmape_to_mape(const nvlist_t *nvl, struct pf_mape_portset *mape)
  540. {
  541. mape->offset = nvlist_get_number(nvl, "offset");
  542. mape->psidlen = nvlist_get_number(nvl, "psidlen");
  543. mape->psid = nvlist_get_number(nvl, "psid");
  544. }
  545. static void
  546. pf_nvpool_to_pool(const nvlist_t *nvl, struct pfctl_pool *pool)
  547. {
  548. size_t len;
  549. const void *data;
  550. data = nvlist_get_binary(nvl, "key", &len);
  551. assert(len == sizeof(pool->key));
  552. memcpy(&pool->key, data, len);
  553. pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "counter"), &pool->counter);
  554. pool->tblidx = nvlist_get_number(nvl, "tblidx");
  555. pf_nvuint_16_array(nvl, "proxy_port", 2, pool->proxy_port, NULL);
  556. pool->opts = nvlist_get_number(nvl, "opts");
  557. if (nvlist_exists_nvlist(nvl, "mape"))
  558. pf_nvmape_to_mape(nvlist_get_nvlist(nvl, "mape"), &pool->mape);
  559. }
  560. static void
  561. pf_nvrule_uid_to_rule_uid(const nvlist_t *nvl, struct pf_rule_uid *uid)
  562. {
  563. pf_nvuint_32_array(nvl, "uid", 2, uid->uid, NULL);
  564. uid->op = nvlist_get_number(nvl, "op");
  565. }
  566. static void
  567. pf_nvdivert_to_divert(const nvlist_t *nvl, struct pfctl_rule *rule)
  568. {
  569. pf_nvaddr_to_addr(nvlist_get_nvlist(nvl, "addr"), &rule->divert.addr);
  570. rule->divert.port = nvlist_get_number(nvl, "port");
  571. }
  572. static void
  573. pf_nvrule_to_rule(const nvlist_t *nvl, struct pfctl_rule *rule)
  574. {
  575. const uint64_t *skip;
  576. const char *const *labels;
  577. size_t skipcount, labelcount;
  578. rule->nr = nvlist_get_number(nvl, "nr");
  579. pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "src"), &rule->src);
  580. pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"), &rule->dst);
  581. skip = nvlist_get_number_array(nvl, "skip", &skipcount);
  582. assert(skip);
  583. assert(skipcount == PF_SKIP_COUNT);
  584. for (int i = 0; i < PF_SKIP_COUNT; i++)
  585. rule->skip[i].nr = skip[i];
  586. labels = nvlist_get_string_array(nvl, "labels", &labelcount);
  587. assert(labelcount <= PF_RULE_MAX_LABEL_COUNT);
  588. for (size_t i = 0; i < labelcount; i++)
  589. strlcpy(rule->label[i], labels[i], PF_RULE_LABEL_SIZE);
  590. rule->ridentifier = nvlist_get_number(nvl, "ridentifier");
  591. strlcpy(rule->ifname, nvlist_get_string(nvl, "ifname"), IFNAMSIZ);
  592. strlcpy(rule->qname, nvlist_get_string(nvl, "qname"), PF_QNAME_SIZE);
  593. strlcpy(rule->pqname, nvlist_get_string(nvl, "pqname"), PF_QNAME_SIZE);
  594. strlcpy(rule->tagname, nvlist_get_string(nvl, "tagname"),
  595. PF_TAG_NAME_SIZE);
  596. strlcpy(rule->match_tagname, nvlist_get_string(nvl, "match_tagname"),
  597. PF_TAG_NAME_SIZE);
  598. strlcpy(rule->overload_tblname, nvlist_get_string(nvl, "overload_tblname"),
  599. PF_TABLE_NAME_SIZE);
  600. pf_nvpool_to_pool(nvlist_get_nvlist(nvl, "rpool"), &rule->rpool);
  601. rule->evaluations = nvlist_get_number(nvl, "evaluations");
  602. pf_nvuint_64_array(nvl, "packets", 2, rule->packets, NULL);
  603. pf_nvuint_64_array(nvl, "bytes", 2, rule->bytes, NULL);
  604. if (nvlist_exists_number(nvl, "timestamp")) {
  605. rule->last_active_timestamp = nvlist_get_number(nvl, "timestamp");
  606. }
  607. rule->os_fingerprint = nvlist_get_number(nvl, "os_fingerprint");
  608. rule->rtableid = nvlist_get_number(nvl, "rtableid");
  609. pf_nvuint_32_array(nvl, "timeout", PFTM_MAX, rule->timeout, NULL);
  610. rule->max_states = nvlist_get_number(nvl, "max_states");
  611. rule->max_src_nodes = nvlist_get_number(nvl, "max_src_nodes");
  612. rule->max_src_states = nvlist_get_number(nvl, "max_src_states");
  613. rule->max_src_conn = nvlist_get_number(nvl, "max_src_conn");
  614. rule->max_src_conn_rate.limit =
  615. nvlist_get_number(nvl, "max_src_conn_rate.limit");
  616. rule->max_src_conn_rate.seconds =
  617. nvlist_get_number(nvl, "max_src_conn_rate.seconds");
  618. rule->qid = nvlist_get_number(nvl, "qid");
  619. rule->pqid = nvlist_get_number(nvl, "pqid");
  620. rule->dnpipe = nvlist_get_number(nvl, "dnpipe");
  621. rule->dnrpipe = nvlist_get_number(nvl, "dnrpipe");
  622. rule->free_flags = nvlist_get_number(nvl, "dnflags");
  623. rule->prob = nvlist_get_number(nvl, "prob");
  624. rule->cuid = nvlist_get_number(nvl, "cuid");
  625. rule->cpid = nvlist_get_number(nvl, "cpid");
  626. rule->return_icmp = nvlist_get_number(nvl, "return_icmp");
  627. rule->return_icmp6 = nvlist_get_number(nvl, "return_icmp6");
  628. rule->max_mss = nvlist_get_number(nvl, "max_mss");
  629. rule->scrub_flags = nvlist_get_number(nvl, "scrub_flags");
  630. pf_nvrule_uid_to_rule_uid(nvlist_get_nvlist(nvl, "uid"), &rule->uid);
  631. pf_nvrule_uid_to_rule_uid(nvlist_get_nvlist(nvl, "gid"),
  632. (struct pf_rule_uid *)&rule->gid);
  633. rule->rule_flag = nvlist_get_number(nvl, "rule_flag");
  634. rule->action = nvlist_get_number(nvl, "action");
  635. rule->direction = nvlist_get_number(nvl, "direction");
  636. rule->log = nvlist_get_number(nvl, "log");
  637. rule->logif = nvlist_get_number(nvl, "logif");
  638. rule->quick = nvlist_get_number(nvl, "quick");
  639. rule->ifnot = nvlist_get_number(nvl, "ifnot");
  640. rule->match_tag_not = nvlist_get_number(nvl, "match_tag_not");
  641. rule->natpass = nvlist_get_number(nvl, "natpass");
  642. rule->keep_state = nvlist_get_number(nvl, "keep_state");
  643. rule->af = nvlist_get_number(nvl, "af");
  644. rule->proto = nvlist_get_number(nvl, "proto");
  645. rule->type = nvlist_get_number(nvl, "type");
  646. rule->code = nvlist_get_number(nvl, "code");
  647. rule->flags = nvlist_get_number(nvl, "flags");
  648. rule->flagset = nvlist_get_number(nvl, "flagset");
  649. rule->min_ttl = nvlist_get_number(nvl, "min_ttl");
  650. rule->allow_opts = nvlist_get_number(nvl, "allow_opts");
  651. rule->rt = nvlist_get_number(nvl, "rt");
  652. rule->return_ttl = nvlist_get_number(nvl, "return_ttl");
  653. rule->tos = nvlist_get_number(nvl, "tos");
  654. rule->set_tos = nvlist_get_number(nvl, "set_tos");
  655. rule->anchor_relative = nvlist_get_number(nvl, "anchor_relative");
  656. rule->anchor_wildcard = nvlist_get_number(nvl, "anchor_wildcard");
  657. rule->flush = nvlist_get_number(nvl, "flush");
  658. rule->prio = nvlist_get_number(nvl, "prio");
  659. pf_nvuint_8_array(nvl, "set_prio", 2, rule->set_prio, NULL);
  660. pf_nvdivert_to_divert(nvlist_get_nvlist(nvl, "divert"), rule);
  661. rule->states_cur = nvlist_get_number(nvl, "states_cur");
  662. rule->states_tot = nvlist_get_number(nvl, "states_tot");
  663. rule->src_nodes = nvlist_get_number(nvl, "src_nodes");
  664. }
  665. static void
  666. pfctl_nveth_addr_to_eth_addr(const nvlist_t *nvl, struct pfctl_eth_addr *addr)
  667. {
  668. static const u_int8_t EMPTY_MAC[ETHER_ADDR_LEN] = { 0 };
  669. size_t len;
  670. const void *data;
  671. data = nvlist_get_binary(nvl, "addr", &len);
  672. assert(len == sizeof(addr->addr));
  673. memcpy(addr->addr, data, sizeof(addr->addr));
  674. data = nvlist_get_binary(nvl, "mask", &len);
  675. assert(len == sizeof(addr->mask));
  676. memcpy(addr->mask, data, sizeof(addr->mask));
  677. addr->neg = nvlist_get_bool(nvl, "neg");
  678. /* To make checks for 'is this address set?' easier. */
  679. addr->isset = memcmp(addr->addr, EMPTY_MAC, ETHER_ADDR_LEN) != 0;
  680. }
  681. static nvlist_t *
  682. pfctl_eth_addr_to_nveth_addr(const struct pfctl_eth_addr *addr)
  683. {
  684. nvlist_t *nvl;
  685. nvl = nvlist_create(0);
  686. if (nvl == NULL)
  687. return (NULL);
  688. nvlist_add_bool(nvl, "neg", addr->neg);
  689. nvlist_add_binary(nvl, "addr", &addr->addr, ETHER_ADDR_LEN);
  690. nvlist_add_binary(nvl, "mask", &addr->mask, ETHER_ADDR_LEN);
  691. return (nvl);
  692. }
  693. static void
  694. pfctl_nveth_rule_to_eth_rule(const nvlist_t *nvl, struct pfctl_eth_rule *rule)
  695. {
  696. const char *const *labels;
  697. size_t labelcount, i;
  698. rule->nr = nvlist_get_number(nvl, "nr");
  699. rule->quick = nvlist_get_bool(nvl, "quick");
  700. strlcpy(rule->ifname, nvlist_get_string(nvl, "ifname"), IFNAMSIZ);
  701. rule->ifnot = nvlist_get_bool(nvl, "ifnot");
  702. rule->direction = nvlist_get_number(nvl, "direction");
  703. rule->proto = nvlist_get_number(nvl, "proto");
  704. strlcpy(rule->match_tagname, nvlist_get_string(nvl, "match_tagname"),
  705. PF_TAG_NAME_SIZE);
  706. rule->match_tag = nvlist_get_number(nvl, "match_tag");
  707. rule->match_tag_not = nvlist_get_bool(nvl, "match_tag_not");
  708. labels = nvlist_get_string_array(nvl, "labels", &labelcount);
  709. assert(labelcount <= PF_RULE_MAX_LABEL_COUNT);
  710. for (i = 0; i < labelcount; i++)
  711. strlcpy(rule->label[i], labels[i], PF_RULE_LABEL_SIZE);
  712. rule->ridentifier = nvlist_get_number(nvl, "ridentifier");
  713. pfctl_nveth_addr_to_eth_addr(nvlist_get_nvlist(nvl, "src"),
  714. &rule->src);
  715. pfctl_nveth_addr_to_eth_addr(nvlist_get_nvlist(nvl, "dst"),
  716. &rule->dst);
  717. pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "ipsrc"),
  718. &rule->ipsrc);
  719. pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "ipdst"),
  720. &rule->ipdst);
  721. rule->evaluations = nvlist_get_number(nvl, "evaluations");
  722. rule->packets[0] = nvlist_get_number(nvl, "packets-in");
  723. rule->packets[1] = nvlist_get_number(nvl, "packets-out");
  724. rule->bytes[0] = nvlist_get_number(nvl, "bytes-in");
  725. rule->bytes[1] = nvlist_get_number(nvl, "bytes-out");
  726. if (nvlist_exists_number(nvl, "timestamp")) {
  727. rule->last_active_timestamp = nvlist_get_number(nvl, "timestamp");
  728. }
  729. strlcpy(rule->qname, nvlist_get_string(nvl, "qname"), PF_QNAME_SIZE);
  730. strlcpy(rule->tagname, nvlist_get_string(nvl, "tagname"),
  731. PF_TAG_NAME_SIZE);
  732. rule->dnpipe = nvlist_get_number(nvl, "dnpipe");
  733. rule->dnflags = nvlist_get_number(nvl, "dnflags");
  734. rule->anchor_relative = nvlist_get_number(nvl, "anchor_relative");
  735. rule->anchor_wildcard = nvlist_get_number(nvl, "anchor_wildcard");
  736. strlcpy(rule->bridge_to, nvlist_get_string(nvl, "bridge_to"),
  737. IFNAMSIZ);
  738. rule->action = nvlist_get_number(nvl, "action");
  739. }
  740. int
  741. pfctl_get_eth_rulesets_info(int dev, struct pfctl_eth_rulesets_info *ri,
  742. const char *path)
  743. {
  744. nvlist_t *nvl;
  745. int ret;
  746. bzero(ri, sizeof(*ri));
  747. nvl = nvlist_create(0);
  748. nvlist_add_string(nvl, "path", path);
  749. if ((ret = pfctl_do_ioctl(dev, DIOCGETETHRULESETS, 256, &nvl)) != 0)
  750. goto out;
  751. ri->nr = nvlist_get_number(nvl, "nr");
  752. out:
  753. nvlist_destroy(nvl);
  754. return (ret);
  755. }
  756. int
  757. pfctl_get_eth_ruleset(int dev, const char *path, int nr,
  758. struct pfctl_eth_ruleset_info *ri)
  759. {
  760. nvlist_t *nvl;
  761. int ret;
  762. bzero(ri, sizeof(*ri));
  763. nvl = nvlist_create(0);
  764. nvlist_add_string(nvl, "path", path);
  765. nvlist_add_number(nvl, "nr", nr);
  766. if ((ret = pfctl_do_ioctl(dev, DIOCGETETHRULESET, 1024, &nvl)) != 0)
  767. goto out;
  768. ri->nr = nvlist_get_number(nvl, "nr");
  769. strlcpy(ri->path, nvlist_get_string(nvl, "path"), MAXPATHLEN);
  770. strlcpy(ri->name, nvlist_get_string(nvl, "name"),
  771. PF_ANCHOR_NAME_SIZE);
  772. out:
  773. nvlist_destroy(nvl);
  774. return (ret);
  775. }
  776. int
  777. pfctl_get_eth_rules_info(int dev, struct pfctl_eth_rules_info *rules,
  778. const char *path)
  779. {
  780. nvlist_t *nvl;
  781. int ret;
  782. bzero(rules, sizeof(*rules));
  783. nvl = nvlist_create(0);
  784. nvlist_add_string(nvl, "anchor", path);
  785. if ((ret = pfctl_do_ioctl(dev, DIOCGETETHRULES, 1024, &nvl)) != 0)
  786. goto out;
  787. rules->nr = nvlist_get_number(nvl, "nr");
  788. rules->ticket = nvlist_get_number(nvl, "ticket");
  789. out:
  790. nvlist_destroy(nvl);
  791. return (ret);
  792. }
  793. int
  794. pfctl_get_eth_rule(int dev, uint32_t nr, uint32_t ticket,
  795. const char *path, struct pfctl_eth_rule *rule, bool clear,
  796. char *anchor_call)
  797. {
  798. nvlist_t *nvl;
  799. int ret;
  800. nvl = nvlist_create(0);
  801. nvlist_add_string(nvl, "anchor", path);
  802. nvlist_add_number(nvl, "ticket", ticket);
  803. nvlist_add_number(nvl, "nr", nr);
  804. nvlist_add_bool(nvl, "clear", clear);
  805. if ((ret = pfctl_do_ioctl(dev, DIOCGETETHRULE, 4096, &nvl)) != 0)
  806. goto out;
  807. pfctl_nveth_rule_to_eth_rule(nvl, rule);
  808. if (anchor_call)
  809. strlcpy(anchor_call, nvlist_get_string(nvl, "anchor_call"),
  810. MAXPATHLEN);
  811. out:
  812. nvlist_destroy(nvl);
  813. return (ret);
  814. }
  815. int
  816. pfctl_add_eth_rule(int dev, const struct pfctl_eth_rule *r, const char *anchor,
  817. const char *anchor_call, uint32_t ticket)
  818. {
  819. struct pfioc_nv nv;
  820. nvlist_t *nvl, *addr;
  821. void *packed;
  822. int error = 0;
  823. size_t labelcount, size;
  824. nvl = nvlist_create(0);
  825. nvlist_add_number(nvl, "ticket", ticket);
  826. nvlist_add_string(nvl, "anchor", anchor);
  827. nvlist_add_string(nvl, "anchor_call", anchor_call);
  828. nvlist_add_number(nvl, "nr", r->nr);
  829. nvlist_add_bool(nvl, "quick", r->quick);
  830. nvlist_add_string(nvl, "ifname", r->ifname);
  831. nvlist_add_bool(nvl, "ifnot", r->ifnot);
  832. nvlist_add_number(nvl, "direction", r->direction);
  833. nvlist_add_number(nvl, "proto", r->proto);
  834. nvlist_add_string(nvl, "match_tagname", r->match_tagname);
  835. nvlist_add_bool(nvl, "match_tag_not", r->match_tag_not);
  836. addr = pfctl_eth_addr_to_nveth_addr(&r->src);
  837. if (addr == NULL) {
  838. nvlist_destroy(nvl);
  839. return (ENOMEM);
  840. }
  841. nvlist_add_nvlist(nvl, "src", addr);
  842. nvlist_destroy(addr);
  843. addr = pfctl_eth_addr_to_nveth_addr(&r->dst);
  844. if (addr == NULL) {
  845. nvlist_destroy(nvl);
  846. return (ENOMEM);
  847. }
  848. nvlist_add_nvlist(nvl, "dst", addr);
  849. nvlist_destroy(addr);
  850. pfctl_nv_add_rule_addr(nvl, "ipsrc", &r->ipsrc);
  851. pfctl_nv_add_rule_addr(nvl, "ipdst", &r->ipdst);
  852. labelcount = 0;
  853. while (labelcount < PF_RULE_MAX_LABEL_COUNT &&
  854. r->label[labelcount][0] != 0) {
  855. nvlist_append_string_array(nvl, "labels",
  856. r->label[labelcount]);
  857. labelcount++;
  858. }
  859. nvlist_add_number(nvl, "ridentifier", r->ridentifier);
  860. nvlist_add_string(nvl, "qname", r->qname);
  861. nvlist_add_string(nvl, "tagname", r->tagname);
  862. nvlist_add_number(nvl, "dnpipe", r->dnpipe);
  863. nvlist_add_number(nvl, "dnflags", r->dnflags);
  864. nvlist_add_string(nvl, "bridge_to", r->bridge_to);
  865. nvlist_add_number(nvl, "action", r->action);
  866. packed = nvlist_pack(nvl, &size);
  867. if (packed == NULL) {
  868. nvlist_destroy(nvl);
  869. return (ENOMEM);
  870. }
  871. nv.len = size;
  872. nv.size = size;
  873. nv.data = packed;
  874. if (ioctl(dev, DIOCADDETHRULE, &nv) != 0)
  875. error = errno;
  876. free(packed);
  877. nvlist_destroy(nvl);
  878. return (error);
  879. }
  880. static void
  881. snl_add_msg_attr_addr_wrap(struct snl_writer *nw, uint32_t type, const struct pf_addr_wrap *addr)
  882. {
  883. int off;
  884. off = snl_add_msg_attr_nested(nw, type);
  885. snl_add_msg_attr_ip6(nw, PF_AT_ADDR, &addr->v.a.addr.v6);
  886. snl_add_msg_attr_ip6(nw, PF_AT_MASK, &addr->v.a.mask.v6);
  887. if (addr->type == PF_ADDR_DYNIFTL)
  888. snl_add_msg_attr_string(nw, PF_AT_IFNAME, addr->v.ifname);
  889. if (addr->type == PF_ADDR_TABLE)
  890. snl_add_msg_attr_string(nw, PF_AT_TABLENAME, addr->v.tblname);
  891. snl_add_msg_attr_u8(nw, PF_AT_TYPE, addr->type);
  892. snl_add_msg_attr_u8(nw, PF_AT_IFLAGS, addr->iflags);
  893. snl_end_attr_nested(nw, off);
  894. }
  895. static void
  896. snl_add_msg_attr_pool_addr(struct snl_writer *nw, uint32_t type, const struct pf_pooladdr *pa)
  897. {
  898. int off;
  899. off = snl_add_msg_attr_nested(nw, type);
  900. snl_add_msg_attr_string(nw, PF_PA_IFNAME, pa->ifname);
  901. snl_add_msg_attr_addr_wrap(nw, PF_PA_ADDR, &pa->addr);
  902. snl_end_attr_nested(nw, off);
  903. }
  904. static void
  905. snl_add_msg_attr_rule_addr(struct snl_writer *nw, uint32_t type, const struct pf_rule_addr *addr)
  906. {
  907. int off;
  908. off = snl_add_msg_attr_nested(nw, type);
  909. snl_add_msg_attr_addr_wrap(nw, PF_RAT_ADDR, &addr->addr);
  910. snl_add_msg_attr_u16(nw, PF_RAT_SRC_PORT, addr->port[0]);
  911. snl_add_msg_attr_u16(nw, PF_RAT_DST_PORT, addr->port[1]);
  912. snl_add_msg_attr_u8(nw, PF_RAT_NEG, addr->neg);
  913. snl_add_msg_attr_u8(nw, PF_RAT_OP, addr->port_op);
  914. snl_end_attr_nested(nw, off);
  915. }
  916. static void
  917. snl_add_msg_attr_rule_labels(struct snl_writer *nw, uint32_t type, const char labels[PF_RULE_MAX_LABEL_COUNT][PF_RULE_LABEL_SIZE])
  918. {
  919. int off, i = 0;
  920. off = snl_add_msg_attr_nested(nw, type);
  921. while (i < PF_RULE_MAX_LABEL_COUNT &&
  922. labels[i][0] != 0) {
  923. snl_add_msg_attr_string(nw, PF_LT_LABEL, labels[i]);
  924. i++;
  925. }
  926. snl_end_attr_nested(nw, off);
  927. }
  928. static void
  929. snl_add_msg_attr_mape(struct snl_writer *nw, uint32_t type, const struct pf_mape_portset *me)
  930. {
  931. int off;
  932. off = snl_add_msg_attr_nested(nw, type);
  933. snl_add_msg_attr_u8(nw, PF_MET_OFFSET, me->offset);
  934. snl_add_msg_attr_u8(nw, PF_MET_PSID_LEN, me->psidlen);
  935. snl_add_msg_attr_u16(nw, PF_MET_PSID, me->psid);
  936. snl_end_attr_nested(nw, off);
  937. }
  938. static void
  939. snl_add_msg_attr_rpool(struct snl_writer *nw, uint32_t type, const struct pfctl_pool *pool)
  940. {
  941. int off;
  942. off = snl_add_msg_attr_nested(nw, type);
  943. snl_add_msg_attr(nw, PF_PT_KEY, sizeof(pool->key), &pool->key);
  944. snl_add_msg_attr_ip6(nw, PF_PT_COUNTER, &pool->counter.v6);
  945. snl_add_msg_attr_u32(nw, PF_PT_TBLIDX, pool->tblidx);
  946. snl_add_msg_attr_u16(nw, PF_PT_PROXY_SRC_PORT, pool->proxy_port[0]);
  947. snl_add_msg_attr_u16(nw, PF_PT_PROXY_DST_PORT, pool->proxy_port[1]);
  948. snl_add_msg_attr_u8(nw, PF_PT_OPTS, pool->opts);
  949. snl_add_msg_attr_mape(nw, PF_PT_MAPE, &pool->mape);
  950. snl_end_attr_nested(nw, off);
  951. }
  952. static void
  953. snl_add_msg_attr_timeouts(struct snl_writer *nw, uint32_t type, const uint32_t *timeouts)
  954. {
  955. int off;
  956. off = snl_add_msg_attr_nested(nw, type);
  957. for (int i = 0; i < PFTM_MAX; i++)
  958. snl_add_msg_attr_u32(nw, PF_TT_TIMEOUT, timeouts[i]);
  959. snl_end_attr_nested(nw, off);
  960. }
  961. static void
  962. snl_add_msg_attr_uid(struct snl_writer *nw, uint32_t type, const struct pf_rule_uid *uid)
  963. {
  964. int off;
  965. off = snl_add_msg_attr_nested(nw, type);
  966. snl_add_msg_attr_u32(nw, PF_RUT_UID_LOW, uid->uid[0]);
  967. snl_add_msg_attr_u32(nw, PF_RUT_UID_HIGH, uid->uid[1]);
  968. snl_add_msg_attr_u8(nw, PF_RUT_OP, uid->op);
  969. snl_end_attr_nested(nw, off);
  970. }
  971. static void
  972. snl_add_msg_attr_pf_rule(struct snl_writer *nw, uint32_t type, const struct pfctl_rule *r)
  973. {
  974. int off;
  975. off = snl_add_msg_attr_nested(nw, type);
  976. snl_add_msg_attr_rule_addr(nw, PF_RT_SRC, &r->src);
  977. snl_add_msg_attr_rule_addr(nw, PF_RT_DST, &r->dst);
  978. snl_add_msg_attr_rule_labels(nw, PF_RT_LABELS, r->label);
  979. snl_add_msg_attr_u32(nw, PF_RT_RIDENTIFIER, r->ridentifier);
  980. snl_add_msg_attr_string(nw, PF_RT_IFNAME, r->ifname);
  981. snl_add_msg_attr_string(nw, PF_RT_QNAME, r->qname);
  982. snl_add_msg_attr_string(nw, PF_RT_PQNAME, r->pqname);
  983. snl_add_msg_attr_string(nw, PF_RT_TAGNAME, r->tagname);
  984. snl_add_msg_attr_string(nw, PF_RT_MATCH_TAGNAME, r->match_tagname);
  985. snl_add_msg_attr_string(nw, PF_RT_OVERLOAD_TBLNAME, r->overload_tblname);
  986. snl_add_msg_attr_rpool(nw, PF_RT_RPOOL, &r->rpool);
  987. snl_add_msg_attr_u32(nw, PF_RT_OS_FINGERPRINT, r->os_fingerprint);
  988. snl_add_msg_attr_u32(nw, PF_RT_RTABLEID, r->rtableid);
  989. snl_add_msg_attr_timeouts(nw, PF_RT_TIMEOUT, r->timeout);
  990. snl_add_msg_attr_u32(nw, PF_RT_MAX_STATES, r->max_states);
  991. snl_add_msg_attr_u32(nw, PF_RT_MAX_SRC_NODES, r->max_src_nodes);
  992. snl_add_msg_attr_u32(nw, PF_RT_MAX_SRC_STATES, r->max_src_states);
  993. snl_add_msg_attr_u32(nw, PF_RT_MAX_SRC_CONN_RATE_LIMIT, r->max_src_conn_rate.limit);
  994. snl_add_msg_attr_u32(nw, PF_RT_MAX_SRC_CONN_RATE_SECS, r->max_src_conn_rate.seconds);
  995. snl_add_msg_attr_u16(nw, PF_RT_DNPIPE, r->dnpipe);
  996. snl_add_msg_attr_u16(nw, PF_RT_DNRPIPE, r->dnrpipe);
  997. snl_add_msg_attr_u32(nw, PF_RT_DNFLAGS, r->free_flags);
  998. snl_add_msg_attr_u32(nw, PF_RT_NR, r->nr);
  999. snl_add_msg_attr_u32(nw, PF_RT_PROB, r->prob);
  1000. snl_add_msg_attr_u32(nw, PF_RT_CUID, r->cuid);
  1001. snl_add_msg_attr_u32(nw, PF_RT_CPID, r->cpid);
  1002. snl_add_msg_attr_u16(nw, PF_RT_RETURN_ICMP, r->return_icmp);
  1003. snl_add_msg_attr_u16(nw, PF_RT_RETURN_ICMP6, r->return_icmp6);
  1004. snl_add_msg_attr_u16(nw, PF_RT_MAX_MSS, r->max_mss);
  1005. snl_add_msg_attr_u16(nw, PF_RT_SCRUB_FLAGS, r->scrub_flags);
  1006. snl_add_msg_attr_uid(nw, PF_RT_UID, &r->uid);
  1007. snl_add_msg_attr_uid(nw, PF_RT_GID, (const struct pf_rule_uid *)&r->gid);
  1008. snl_add_msg_attr_u32(nw, PF_RT_RULE_FLAG, r->rule_flag);
  1009. snl_add_msg_attr_u8(nw, PF_RT_ACTION, r->action);
  1010. snl_add_msg_attr_u8(nw, PF_RT_DIRECTION, r->direction);
  1011. snl_add_msg_attr_u8(nw, PF_RT_LOG, r->log);
  1012. snl_add_msg_attr_u8(nw, PF_RT_LOGIF, r->logif);
  1013. snl_add_msg_attr_u8(nw, PF_RT_QUICK, r->quick);
  1014. snl_add_msg_attr_u8(nw, PF_RT_IF_NOT, r->ifnot);
  1015. snl_add_msg_attr_u8(nw, PF_RT_MATCH_TAG_NOT, r->match_tag_not);
  1016. snl_add_msg_attr_u8(nw, PF_RT_NATPASS, r->natpass);
  1017. snl_add_msg_attr_u8(nw, PF_RT_KEEP_STATE, r->keep_state);
  1018. snl_add_msg_attr_u8(nw, PF_RT_AF, r->af);
  1019. snl_add_msg_attr_u8(nw, PF_RT_PROTO, r->proto);
  1020. snl_add_msg_attr_u8(nw, PF_RT_TYPE, r->type);
  1021. snl_add_msg_attr_u8(nw, PF_RT_CODE, r->code);
  1022. snl_add_msg_attr_u8(nw, PF_RT_FLAGS, r->flags);
  1023. snl_add_msg_attr_u8(nw, PF_RT_FLAGSET, r->flagset);
  1024. snl_add_msg_attr_u8(nw, PF_RT_MIN_TTL, r->min_ttl);
  1025. snl_add_msg_attr_u8(nw, PF_RT_ALLOW_OPTS, r->allow_opts);
  1026. snl_add_msg_attr_u8(nw, PF_RT_RT, r->rt);
  1027. snl_add_msg_attr_u8(nw, PF_RT_RETURN_TTL, r->return_ttl);
  1028. snl_add_msg_attr_u8(nw, PF_RT_TOS, r->tos);
  1029. snl_add_msg_attr_u8(nw, PF_RT_SET_TOS, r->set_tos);
  1030. snl_add_msg_attr_u8(nw, PF_RT_ANCHOR_RELATIVE, r->anchor_relative);
  1031. snl_add_msg_attr_u8(nw, PF_RT_ANCHOR_WILDCARD, r->anchor_wildcard);
  1032. snl_add_msg_attr_u8(nw, PF_RT_FLUSH, r->flush);
  1033. snl_add_msg_attr_u8(nw, PF_RT_PRIO, r->prio);
  1034. snl_add_msg_attr_u8(nw, PF_RT_SET_PRIO, r->set_prio[0]);
  1035. snl_add_msg_attr_u8(nw, PF_RT_SET_PRIO_REPLY, r->set_prio[1]);
  1036. snl_add_msg_attr_ip6(nw, PF_RT_DIVERT_ADDRESS, &r->divert.addr.v6);
  1037. snl_add_msg_attr_u16(nw, PF_RT_DIVERT_PORT, r->divert.port);
  1038. snl_end_attr_nested(nw, off);
  1039. }
  1040. int
  1041. pfctl_add_rule(int dev __unused, const struct pfctl_rule *r, const char *anchor,
  1042. const char *anchor_call, uint32_t ticket, uint32_t pool_ticket)
  1043. {
  1044. struct pfctl_handle *h;
  1045. int ret;
  1046. h = pfctl_open(PF_DEVICE);
  1047. if (h == NULL)
  1048. return (ENODEV);
  1049. ret = pfctl_add_rule_h(h, r, anchor, anchor_call, ticket, pool_ticket);
  1050. pfctl_close(h);
  1051. return (ret);
  1052. }
  1053. int
  1054. pfctl_add_rule_h(struct pfctl_handle *h, const struct pfctl_rule *r,
  1055. const char *anchor, const char *anchor_call, uint32_t ticket,
  1056. uint32_t pool_ticket)
  1057. {
  1058. struct snl_writer nw;
  1059. struct snl_errmsg_data e = {};
  1060. struct nlmsghdr *hdr;
  1061. uint32_t seq_id;
  1062. int family_id;
  1063. family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME);
  1064. if (family_id == 0)
  1065. return (ENOTSUP);
  1066. snl_init_writer(&h->ss, &nw);
  1067. hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_ADDRULE);
  1068. hdr->nlmsg_flags |= NLM_F_DUMP;
  1069. snl_add_msg_attr_u32(&nw, PF_ART_TICKET, ticket);
  1070. snl_add_msg_attr_u32(&nw, PF_ART_POOL_TICKET, pool_ticket);
  1071. snl_add_msg_attr_string(&nw, PF_ART_ANCHOR, anchor);
  1072. snl_add_msg_attr_string(&nw, PF_ART_ANCHOR_CALL, anchor_call);
  1073. snl_add_msg_attr_pf_rule(&nw, PF_ART_RULE, r);
  1074. if ((hdr = snl_finalize_msg(&nw)) == NULL)
  1075. return (ENXIO);
  1076. seq_id = hdr->nlmsg_seq;
  1077. if (! snl_send_message(&h->ss, hdr))
  1078. return (ENXIO);
  1079. while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
  1080. }
  1081. return (e.error);
  1082. }
  1083. #define _IN(_field) offsetof(struct genlmsghdr, _field)
  1084. #define _OUT(_field) offsetof(struct pfctl_rules_info, _field)
  1085. static struct snl_attr_parser ap_getrules[] = {
  1086. { .type = PF_GR_NR, .off = _OUT(nr), .cb = snl_attr_get_uint32 },
  1087. { .type = PF_GR_TICKET, .off = _OUT(ticket), .cb = snl_attr_get_uint32 },
  1088. };
  1089. static struct snl_field_parser fp_getrules[] = {
  1090. };
  1091. #undef _IN
  1092. #undef _OUT
  1093. SNL_DECLARE_PARSER(getrules_parser, struct genlmsghdr, fp_getrules, ap_getrules);
  1094. int
  1095. pfctl_get_rules_info_h(struct pfctl_handle *h, struct pfctl_rules_info *rules, uint32_t ruleset,
  1096. const char *path)
  1097. {
  1098. struct snl_errmsg_data e = {};
  1099. struct nlmsghdr *hdr;
  1100. struct snl_writer nw;
  1101. uint32_t seq_id;
  1102. int family_id;
  1103. family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME);
  1104. if (family_id == 0)
  1105. return (ENOTSUP);
  1106. snl_init_writer(&h->ss, &nw);
  1107. hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GETRULES);
  1108. hdr->nlmsg_flags |= NLM_F_DUMP;
  1109. snl_add_msg_attr_string(&nw, PF_GR_ANCHOR, path);
  1110. snl_add_msg_attr_u8(&nw, PF_GR_ACTION, ruleset);
  1111. hdr = snl_finalize_msg(&nw);
  1112. if (hdr == NULL)
  1113. return (ENOMEM);
  1114. seq_id = hdr->nlmsg_seq;
  1115. if (! snl_send_message(&h->ss, hdr))
  1116. return (ENXIO);
  1117. while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
  1118. if (! snl_parse_nlmsg(&h->ss, hdr, &getrules_parser, rules))
  1119. continue;
  1120. }
  1121. return (e.error);
  1122. }
  1123. int
  1124. pfctl_get_rules_info(int dev __unused, struct pfctl_rules_info *rules, uint32_t ruleset,
  1125. const char *path)
  1126. {
  1127. struct pfctl_handle *h;
  1128. int error;
  1129. h = pfctl_open(PF_DEVICE);
  1130. if (h == NULL)
  1131. return (ENOTSUP);
  1132. error = pfctl_get_rules_info_h(h, rules, ruleset, path);
  1133. pfctl_close(h);
  1134. return (error);
  1135. }
  1136. int
  1137. pfctl_get_rule_h(struct pfctl_handle *h, uint32_t nr, uint32_t ticket, const char *anchor,
  1138. uint32_t ruleset, struct pfctl_rule *rule, char *anchor_call)
  1139. {
  1140. return (pfctl_get_clear_rule_h(h, nr, ticket, anchor, ruleset, rule,
  1141. anchor_call, false));
  1142. }
  1143. int
  1144. pfctl_get_rule(int dev, uint32_t nr, uint32_t ticket, const char *anchor,
  1145. uint32_t ruleset, struct pfctl_rule *rule, char *anchor_call)
  1146. {
  1147. return (pfctl_get_clear_rule(dev, nr, ticket, anchor, ruleset, rule,
  1148. anchor_call, false));
  1149. }
  1150. #define _OUT(_field) offsetof(struct pf_addr_wrap, _field)
  1151. static const struct snl_attr_parser ap_addr_wrap[] = {
  1152. { .type = PF_AT_ADDR, .off = _OUT(v.a.addr), .cb = snl_attr_get_in6_addr },
  1153. { .type = PF_AT_MASK, .off = _OUT(v.a.mask), .cb = snl_attr_get_in6_addr },
  1154. { .type = PF_AT_IFNAME, .off = _OUT(v.ifname), .arg = (void *)IFNAMSIZ,.cb = snl_attr_copy_string },
  1155. { .type = PF_AT_TABLENAME, .off = _OUT(v.tblname), .arg = (void *)PF_TABLE_NAME_SIZE, .cb = snl_attr_copy_string },
  1156. { .type = PF_AT_TYPE, .off = _OUT(type), .cb = snl_attr_get_uint8 },
  1157. { .type = PF_AT_IFLAGS, .off = _OUT(iflags), .cb = snl_attr_get_uint8 },
  1158. { .type = PF_AT_TBLCNT, .off = _OUT(p.tblcnt), .cb = snl_attr_get_uint32 },
  1159. { .type = PF_AT_DYNCNT, .off = _OUT(p.dyncnt), .cb = snl_attr_get_uint32 },
  1160. };
  1161. SNL_DECLARE_ATTR_PARSER(addr_wrap_parser, ap_addr_wrap);
  1162. #undef _OUT
  1163. #define _OUT(_field) offsetof(struct pf_rule_addr, _field)
  1164. static struct snl_attr_parser ap_rule_addr[] = {
  1165. { .type = PF_RAT_ADDR, .off = _OUT(addr), .arg = &addr_wrap_parser, .cb = snl_attr_get_nested },
  1166. { .type = PF_RAT_SRC_PORT, .off = _OUT(port[0]), .cb = snl_attr_get_uint16 },
  1167. { .type = PF_RAT_DST_PORT, .off = _OUT(port[1]), .cb = snl_attr_get_uint16 },
  1168. { .type = PF_RAT_NEG, .off = _OUT(neg), .cb = snl_attr_get_uint8 },
  1169. { .type = PF_RAT_OP, .off = _OUT(port_op), .cb = snl_attr_get_uint8 },
  1170. };
  1171. #undef _OUT
  1172. SNL_DECLARE_ATTR_PARSER(rule_addr_parser, ap_rule_addr);
  1173. struct snl_parsed_labels
  1174. {
  1175. char labels[PF_RULE_MAX_LABEL_COUNT][PF_RULE_LABEL_SIZE];
  1176. uint32_t i;
  1177. };
  1178. static bool
  1179. snl_attr_get_pf_rule_labels(struct snl_state *ss, struct nlattr *nla,
  1180. const void *arg __unused, void *target)
  1181. {
  1182. struct snl_parsed_labels *l = (struct snl_parsed_labels *)target;
  1183. bool ret;
  1184. if (l->i >= PF_RULE_MAX_LABEL_COUNT)
  1185. return (E2BIG);
  1186. ret = snl_attr_copy_string(ss, nla, (void *)PF_RULE_LABEL_SIZE,
  1187. l->labels[l->i]);
  1188. if (ret)
  1189. l->i++;
  1190. return (ret);
  1191. }
  1192. #define _OUT(_field) offsetof(struct nl_parsed_labels, _field)
  1193. static const struct snl_attr_parser ap_labels[] = {
  1194. { .type = PF_LT_LABEL, .off = 0, .cb = snl_attr_get_pf_rule_labels },
  1195. };
  1196. SNL_DECLARE_ATTR_PARSER(rule_labels_parser, ap_labels);
  1197. #undef _OUT
  1198. static bool
  1199. snl_attr_get_nested_pf_rule_labels(struct snl_state *ss, struct nlattr *nla,
  1200. const void *arg __unused, void *target)
  1201. {
  1202. struct snl_parsed_labels parsed_labels = { };
  1203. bool error;
  1204. /* Assumes target points to the beginning of the structure */
  1205. error = snl_parse_header(ss, NLA_DATA(nla), NLA_DATA_LEN(nla), &rule_labels_parser, &parsed_labels);
  1206. if (! error)
  1207. return (error);
  1208. memcpy(target, parsed_labels.labels, sizeof(parsed_labels.labels));
  1209. return (true);
  1210. }
  1211. #define _OUT(_field) offsetof(struct pf_mape_portset, _field)
  1212. static const struct snl_attr_parser ap_mape_portset[] = {
  1213. { .type = PF_MET_OFFSET, .off = _OUT(offset), .cb = snl_attr_get_uint8 },
  1214. { .type = PF_MET_PSID_LEN, .off = _OUT(psidlen), .cb = snl_attr_get_uint8 },
  1215. {. type = PF_MET_PSID, .off = _OUT(psid), .cb = snl_attr_get_uint16 },
  1216. };
  1217. SNL_DECLARE_ATTR_PARSER(mape_portset_parser, ap_mape_portset);
  1218. #undef _OUT
  1219. #define _OUT(_field) offsetof(struct pfctl_pool, _field)
  1220. static const struct snl_attr_parser ap_pool[] = {
  1221. { .type = PF_PT_KEY, .off = _OUT(key), .arg = (void *)sizeof(struct pf_poolhashkey), .cb = snl_attr_get_bytes },
  1222. { .type = PF_PT_COUNTER, .off = _OUT(counter), .cb = snl_attr_get_in6_addr },
  1223. { .type = PF_PT_TBLIDX, .off = _OUT(tblidx), .cb = snl_attr_get_uint32 },
  1224. { .type = PF_PT_PROXY_SRC_PORT, .off = _OUT(proxy_port[0]), .cb = snl_attr_get_uint16 },
  1225. { .type = PF_PT_PROXY_DST_PORT, .off = _OUT(proxy_port[1]), .cb = snl_attr_get_uint16 },
  1226. { .type = PF_PT_OPTS, .off = _OUT(opts), .cb = snl_attr_get_uint8 },
  1227. { .type = PF_PT_MAPE, .off = _OUT(mape), .arg = &mape_portset_parser, .cb = snl_attr_get_nested },
  1228. };
  1229. SNL_DECLARE_ATTR_PARSER(pool_parser, ap_pool);
  1230. #undef _OUT
  1231. struct nl_parsed_timeouts
  1232. {
  1233. uint32_t timeouts[PFTM_MAX];
  1234. uint32_t i;
  1235. };
  1236. static bool
  1237. snl_attr_get_pf_timeout(struct snl_state *ss, struct nlattr *nla,
  1238. const void *arg __unused, void *target)
  1239. {
  1240. struct nl_parsed_timeouts *t = (struct nl_parsed_timeouts *)target;
  1241. bool ret;
  1242. if (t->i >= PFTM_MAX)
  1243. return (E2BIG);
  1244. ret = snl_attr_get_uint32(ss, nla, NULL, &t->timeouts[t->i]);
  1245. if (ret)
  1246. t->i++;
  1247. return (ret);
  1248. }
  1249. #define _OUT(_field) offsetof(struct nl_parsed_timeout, _field)
  1250. static const struct snl_attr_parser ap_timeouts[] = {
  1251. { .type = PF_TT_TIMEOUT, .off = 0, .cb = snl_attr_get_pf_timeout },
  1252. };
  1253. SNL_DECLARE_ATTR_PARSER(timeout_parser, ap_timeouts);
  1254. #undef _OUT
  1255. static bool
  1256. snl_attr_get_nested_timeouts(struct snl_state *ss, struct nlattr *nla,
  1257. const void *arg __unused, void *target)
  1258. {
  1259. struct nl_parsed_timeouts parsed_timeouts = { };
  1260. bool error;
  1261. /* Assumes target points to the beginning of the structure */
  1262. error = snl_parse_header(ss, NLA_DATA(nla), NLA_DATA_LEN(nla), &timeout_parser, &parsed_timeouts);
  1263. if (! error)
  1264. return (error);
  1265. memcpy(target, parsed_timeouts.timeouts, sizeof(parsed_timeouts.timeouts));
  1266. return (true);
  1267. }
  1268. #define _OUT(_field) offsetof(struct pf_rule_uid, _field)
  1269. static const struct snl_attr_parser ap_rule_uid[] = {
  1270. { .type = PF_RUT_UID_LOW, .off = _OUT(uid[0]), .cb = snl_attr_get_uint32 },
  1271. { .type = PF_RUT_UID_HIGH, .off = _OUT(uid[1]), .cb = snl_attr_get_uint32 },
  1272. { .type = PF_RUT_OP, .off = _OUT(op), .cb = snl_attr_get_uint8 },
  1273. };
  1274. SNL_DECLARE_ATTR_PARSER(rule_uid_parser, ap_rule_uid);
  1275. #undef _OUT
  1276. struct pfctl_nl_get_rule {
  1277. struct pfctl_rule r;
  1278. char anchor_call[MAXPATHLEN];
  1279. };
  1280. #define _OUT(_field) offsetof(struct pfctl_nl_get_rule, _field)
  1281. static struct snl_attr_parser ap_getrule[] = {
  1282. { .type = PF_RT_SRC, .off = _OUT(r.src), .arg = &rule_addr_parser,.cb = snl_attr_get_nested },
  1283. { .type = PF_RT_DST, .off = _OUT(r.dst), .arg = &rule_addr_parser,.cb = snl_attr_get_nested },
  1284. { .type = PF_RT_RIDENTIFIER, .off = _OUT(r.ridentifier), .cb = snl_attr_get_uint32 },
  1285. { .type = PF_RT_LABELS, .off = _OUT(r.label), .arg = &rule_labels_parser,.cb = snl_attr_get_nested_pf_rule_labels },
  1286. { .type = PF_RT_IFNAME, .off = _OUT(r.ifname), .arg = (void *)IFNAMSIZ, .cb = snl_attr_copy_string },
  1287. { .type = PF_RT_QNAME, .off = _OUT(r.qname), .arg = (void *)PF_QNAME_SIZE, .cb = snl_attr_copy_string },
  1288. { .type = PF_RT_PQNAME, .off = _OUT(r.pqname), .arg = (void *)PF_QNAME_SIZE, .cb = snl_attr_copy_string },
  1289. { .type = PF_RT_TAGNAME, .off = _OUT(r.tagname), .arg = (void *)PF_TAG_NAME_SIZE, .cb = snl_attr_copy_string },
  1290. { .type = PF_RT_MATCH_TAGNAME, .off = _OUT(r.match_tagname), .arg = (void *)PF_TAG_NAME_SIZE, .cb = snl_attr_copy_string },
  1291. { .type = PF_RT_OVERLOAD_TBLNAME, .off = _OUT(r.overload_tblname), .arg = (void *)PF_TABLE_NAME_SIZE, .cb = snl_attr_copy_string },
  1292. { .type = PF_RT_RPOOL, .off = _OUT(r.rpool), .arg = &pool_parser, .cb = snl_attr_get_nested },
  1293. { .type = PF_RT_OS_FINGERPRINT, .off = _OUT(r.os_fingerprint), .cb = snl_attr_get_uint32 },
  1294. { .type = PF_RT_RTABLEID, .off = _OUT(r.rtableid), .cb = snl_attr_get_uint32 },
  1295. { .type = PF_RT_TIMEOUT, .off = _OUT(r.timeout), .arg = &timeout_parser, .cb = snl_attr_get_nested_timeouts },
  1296. { .type = PF_RT_MAX_STATES, .off = _OUT(r.max_states), .cb = snl_attr_get_uint32 },
  1297. { .type = PF_RT_MAX_SRC_NODES, .off = _OUT(r.max_src_nodes), .cb = snl_attr_get_uint32 },
  1298. { .type = PF_RT_MAX_SRC_STATES, .off = _OUT(r.max_src_states), .cb = snl_attr_get_uint32 },
  1299. { .type = PF_RT_MAX_SRC_CONN_RATE_LIMIT, .off = _OUT(r.max_src_conn_rate.limit), .cb = snl_attr_get_uint32 },
  1300. { .type = PF_RT_MAX_SRC_CONN_RATE_SECS, .off = _OUT(r.max_src_conn_rate.seconds), .cb = snl_attr_get_uint32 },
  1301. { .type = PF_RT_DNPIPE, .off = _OUT(r.dnpipe), .cb = snl_attr_get_uint16 },
  1302. { .type = PF_RT_DNRPIPE, .off = _OUT(r.dnrpipe), .cb = snl_attr_get_uint16 },
  1303. { .type = PF_RT_DNFLAGS, .off = _OUT(r.free_flags), .cb = snl_attr_get_uint32 },
  1304. { .type = PF_RT_NR, .off = _OUT(r.nr), .cb = snl_attr_get_uint32 },
  1305. { .type = PF_RT_PROB, .off = _OUT(r.prob), .cb = snl_attr_get_uint32 },
  1306. { .type = PF_RT_CUID, .off = _OUT(r.cuid), .cb = snl_attr_get_uint32 },
  1307. {. type = PF_RT_CPID, .off = _OUT(r.cpid), .cb = snl_attr_get_uint32 },
  1308. { .type = PF_RT_RETURN_ICMP, .off = _OUT(r.return_icmp), .cb = snl_attr_get_uint16 },
  1309. { .type = PF_RT_RETURN_ICMP6, .off = _OUT(r.return_icmp6), .cb = snl_attr_get_uint16 },
  1310. { .type = PF_RT_MAX_MSS, .off = _OUT(r.max_mss), .cb = snl_attr_get_uint16 },
  1311. { .type = PF_RT_SCRUB_FLAGS, .off = _OUT(r.scrub_flags), .cb = snl_attr_get_uint16 },
  1312. { .type = PF_RT_UID, .off = _OUT(r.uid), .arg = &rule_uid_parser, .cb = snl_attr_get_nested },
  1313. { .type = PF_RT_GID, .off = _OUT(r.gid), .arg = &rule_uid_parser, .cb = snl_attr_get_nested },
  1314. { .type = PF_RT_RULE_FLAG, .off = _OUT(r.rule_flag), .cb = snl_attr_get_uint32 },
  1315. { .type = PF_RT_ACTION, .off = _OUT(r.action), .cb = snl_attr_get_uint8 },
  1316. { .type = PF_RT_DIRECTION, .off = _OUT(r.direction), .cb = snl_attr_get_uint8 },
  1317. { .type = PF_RT_LOG, .off = _OUT(r.log), .cb = snl_attr_get_uint8 },
  1318. { .type = PF_RT_LOGIF, .off = _OUT(r.logif), .cb = snl_attr_get_uint8 },
  1319. { .type = PF_RT_QUICK, .off = _OUT(r.quick), .cb = snl_attr_get_uint8 },
  1320. { .type = PF_RT_IF_NOT, .off = _OUT(r.ifnot), .cb = snl_attr_get_uint8 },
  1321. { .type = PF_RT_MATCH_TAG_NOT, .off = _OUT(r.match_tag_not), .cb = snl_attr_get_uint8 },
  1322. { .type = PF_RT_NATPASS, .off = _OUT(r.natpass), .cb = snl_attr_get_uint8 },
  1323. { .type = PF_RT_KEEP_STATE, .off = _OUT(r.keep_state), .cb = snl_attr_get_uint8 },
  1324. { .type = PF_RT_AF, .off = _OUT(r.af), .cb = snl_attr_get_uint8 },
  1325. { .type = PF_RT_PROTO, .off = _OUT(r.proto), .cb = snl_attr_get_uint8 },
  1326. { .type = PF_RT_TYPE, .off = _OUT(r.type), .cb = snl_attr_get_uint8 },
  1327. { .type = PF_RT_CODE, .off = _OUT(r.code), .cb = snl_attr_get_uint8 },
  1328. { .type = PF_RT_FLAGS, .off = _OUT(r.flags), .cb = snl_attr_get_uint8 },
  1329. { .type = PF_RT_FLAGSET, .off = _OUT(r.flagset), .cb = snl_attr_get_uint8 },
  1330. { .type = PF_RT_MIN_TTL, .off = _OUT(r.min_ttl), .cb = snl_attr_get_uint8 },
  1331. { .type = PF_RT_ALLOW_OPTS, .off = _OUT(r.allow_opts), .cb = snl_attr_get_uint8 },
  1332. { .type = PF_RT_RT, .off = _OUT(r.rt), .cb = snl_attr_get_uint8 },
  1333. { .type = PF_RT_RETURN_TTL, .off = _OUT(r.return_ttl), .cb = snl_attr_get_uint8 },
  1334. { .type = PF_RT_TOS, .off = _OUT(r.tos), .cb = snl_attr_get_uint8 },
  1335. { .type = PF_RT_SET_TOS, .off = _OUT(r.set_tos), .cb = snl_attr_get_uint8 },
  1336. { .type = PF_RT_ANCHOR_RELATIVE, .off = _OUT(r.anchor_relative), .cb = snl_attr_get_uint8 },
  1337. { .type = PF_RT_ANCHOR_WILDCARD, .off = _OUT(r.anchor_wildcard), .cb = snl_attr_get_uint8 },
  1338. { .type = PF_RT_FLUSH, .off = _OUT(r.flush), .cb = snl_attr_get_uint8 },
  1339. { .type = PF_RT_PRIO, .off = _OUT(r.prio), .cb = snl_attr_get_uint8 },
  1340. { .type = PF_RT_SET_PRIO, .off = _OUT(r.set_prio[0]), .cb = snl_attr_get_uint8 },
  1341. { .type = PF_RT_SET_PRIO_REPLY, .off = _OUT(r.set_prio[1]), .cb = snl_attr_get_uint8 },
  1342. { .type = PF_RT_DIVERT_ADDRESS, .off = _OUT(r.divert.addr), .cb = snl_attr_get_in6_addr },
  1343. { .type = PF_RT_DIVERT_PORT, .off = _OUT(r.divert.port), .cb = snl_attr_get_uint16 },
  1344. { .type = PF_RT_PACKETS_IN, .off = _OUT(r.packets[0]), .cb = snl_attr_get_uint64 },
  1345. { .type = PF_RT_PACKETS_OUT, .off = _OUT(r.packets[1]), .cb = snl_attr_get_uint64 },
  1346. { .type = PF_RT_BYTES_IN, .off = _OUT(r.bytes[0]), .cb = snl_attr_get_uint64 },
  1347. { .type = PF_RT_BYTES_OUT, .off = _OUT(r.bytes[1]), .cb = snl_attr_get_uint64 },
  1348. { .type = PF_RT_EVALUATIONS, .off = _OUT(r.evaluations), .cb = snl_attr_get_uint64 },
  1349. { .type = PF_RT_TIMESTAMP, .off = _OUT(r.last_active_timestamp), .cb = snl_attr_get_uint64 },
  1350. { .type = PF_RT_STATES_CUR, .off = _OUT(r.states_cur), .cb = snl_attr_get_uint64 },
  1351. { .type = PF_RT_STATES_TOTAL, .off = _OUT(r.states_tot), .cb = snl_attr_get_uint64 },
  1352. { .type = PF_RT_SRC_NODES, .off = _OUT(r.src_nodes), .cb = snl_attr_get_uint64 },
  1353. { .type = PF_RT_ANCHOR_CALL, .off = _OUT(anchor_call), .arg = (void*)MAXPATHLEN, .cb = snl_attr_copy_string },
  1354. };
  1355. static struct snl_field_parser fp_getrule[] = {};
  1356. #undef _OUT
  1357. SNL_DECLARE_PARSER(getrule_parser, struct genlmsghdr, fp_getrule, ap_getrule);
  1358. int
  1359. pfctl_get_clear_rule_h(struct pfctl_handle *h, uint32_t nr, uint32_t ticket,
  1360. const char *anchor, uint32_t ruleset, struct pfctl_rule *rule,
  1361. char *anchor_call, bool clear)
  1362. {
  1363. struct pfctl_nl_get_rule attrs = {};
  1364. struct snl_errmsg_data e = {};
  1365. struct nlmsghdr *hdr;
  1366. struct snl_writer nw;
  1367. uint32_t seq_id;
  1368. int family_id;
  1369. family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME);
  1370. if (family_id == 0)
  1371. return (ENOTSUP);
  1372. snl_init_writer(&h->ss, &nw);
  1373. hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GETRULE);
  1374. hdr->nlmsg_flags |= NLM_F_DUMP;
  1375. snl_add_msg_attr_string(&nw, PF_GR_ANCHOR, anchor);
  1376. snl_add_msg_attr_u8(&nw, PF_GR_ACTION, ruleset);
  1377. snl_add_msg_attr_u32(&nw, PF_GR_NR, nr);
  1378. snl_add_msg_attr_u32(&nw, PF_GR_TICKET, ticket);
  1379. snl_add_msg_attr_u8(&nw, PF_GR_CLEAR, clear);
  1380. hdr = snl_finalize_msg(&nw);
  1381. if (hdr == NULL)
  1382. return (ENOMEM);
  1383. seq_id = hdr->nlmsg_seq;
  1384. if (! snl_send_message(&h->ss, hdr))
  1385. return (ENXIO);
  1386. while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
  1387. if (! snl_parse_nlmsg(&h->ss, hdr, &getrule_parser, &attrs))
  1388. continue;
  1389. }
  1390. memcpy(rule, &attrs.r, sizeof(attrs.r));
  1391. strlcpy(anchor_call, attrs.anchor_call, MAXPATHLEN);
  1392. return (e.error);
  1393. }
  1394. int
  1395. pfctl_get_clear_rule(int dev, uint32_t nr, uint32_t ticket,
  1396. const char *anchor, uint32_t ruleset, struct pfctl_rule *rule,
  1397. char *anchor_call, bool clear)
  1398. {
  1399. nvlist_t *nvl;
  1400. int ret;
  1401. nvl = nvlist_create(0);
  1402. if (nvl == 0)
  1403. return (ENOMEM);
  1404. nvlist_add_number(nvl, "nr", nr);
  1405. nvlist_add_number(nvl, "ticket", ticket);
  1406. nvlist_add_string(nvl, "anchor", anchor);
  1407. nvlist_add_number(nvl, "ruleset", ruleset);
  1408. if (clear)
  1409. nvlist_add_bool(nvl, "clear_counter", true);
  1410. if ((ret = pfctl_do_ioctl(dev, DIOCGETRULENV, 8192, &nvl)) != 0)
  1411. goto out;
  1412. pf_nvrule_to_rule(nvlist_get_nvlist(nvl, "rule"), rule);
  1413. if (anchor_call)
  1414. strlcpy(anchor_call, nvlist_get_string(nvl, "anchor_call"),
  1415. MAXPATHLEN);
  1416. out:
  1417. nvlist_destroy(nvl);
  1418. return (ret);
  1419. }
  1420. int
  1421. pfctl_set_keepcounters(int dev, bool keep)
  1422. {
  1423. struct pfioc_nv nv;
  1424. nvlist_t *nvl;
  1425. int ret;
  1426. nvl = nvlist_create(0);
  1427. nvlist_add_bool(nvl, "keep_counters", keep);
  1428. nv.data = nvlist_pack(nvl, &nv.len);
  1429. nv.size = nv.len;
  1430. nvlist_destroy(nvl);
  1431. ret = ioctl(dev, DIOCKEEPCOUNTERS, &nv);
  1432. free(nv.data);
  1433. return (ret);
  1434. }
  1435. struct pfctl_creator {
  1436. uint32_t id;
  1437. };
  1438. #define _IN(_field) offsetof(struct genlmsghdr, _field)
  1439. #define _OUT(_field) offsetof(struct pfctl_creator, _field)
  1440. static struct snl_attr_parser ap_creators[] = {
  1441. { .type = PF_ST_CREATORID, .off = _OUT(id), .cb = snl_attr_get_uint32 },
  1442. };
  1443. static struct snl_field_parser fp_creators[] = {
  1444. };
  1445. #undef _IN
  1446. #undef _OUT
  1447. SNL_DECLARE_PARSER(creator_parser, struct genlmsghdr, fp_creators, ap_creators);
  1448. static int
  1449. pfctl_get_creators_nl(struct snl_state *ss, uint32_t *creators, size_t *len)
  1450. {
  1451. int family_id = snl_get_genl_family(ss, PFNL_FAMILY_NAME);
  1452. size_t i = 0;
  1453. struct nlmsghdr *hdr;
  1454. struct snl_writer nw;
  1455. if (family_id == 0)
  1456. return (ENOTSUP);
  1457. snl_init_writer(ss, &nw);
  1458. hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GETCREATORS);
  1459. hdr->nlmsg_flags |= NLM_F_DUMP;
  1460. hdr = snl_finalize_msg(&nw);
  1461. if (hdr == NULL)
  1462. return (ENOMEM);
  1463. uint32_t seq_id = hdr->nlmsg_seq;
  1464. snl_send_message(ss, hdr);
  1465. struct snl_errmsg_data e = {};
  1466. while ((hdr = snl_read_reply_multi(ss, seq_id, &e)) != NULL) {
  1467. struct pfctl_creator c;
  1468. bzero(&c, sizeof(c));
  1469. if (!snl_parse_nlmsg(ss, hdr, &creator_parser, &c))
  1470. continue;
  1471. creators[i] = c.id;
  1472. i++;
  1473. if (i > *len)
  1474. return (E2BIG);
  1475. }
  1476. *len = i;
  1477. return (0);
  1478. }
  1479. int
  1480. pfctl_get_creatorids(struct pfctl_handle *h, uint32_t *creators, size_t *len)
  1481. {
  1482. int error;
  1483. error = pfctl_get_creators_nl(&h->ss, creators, len);
  1484. return (error);
  1485. }
  1486. static inline bool
  1487. snl_attr_get_pfaddr(struct snl_state *ss __unused, struct nlattr *nla,
  1488. const void *arg __unused, void *target)
  1489. {
  1490. memcpy(target, NLA_DATA(nla), NLA_DATA_LEN(nla));
  1491. return (true);
  1492. }
  1493. static inline bool
  1494. snl_attr_store_ifname(struct snl_state *ss __unused, struct nlattr *nla,
  1495. const void *arg __unused, void *target)
  1496. {
  1497. size_t maxlen = NLA_DATA_LEN(nla);
  1498. if (strnlen((char *)NLA_DATA(nla), maxlen) < maxlen) {
  1499. strlcpy(target, (char *)NLA_DATA(nla), maxlen);
  1500. return (true);
  1501. }
  1502. return (false);
  1503. }
  1504. #define _OUT(_field) offsetof(struct pfctl_state_peer, _field)
  1505. static const struct snl_attr_parser nla_p_speer[] = {
  1506. { .type = PF_STP_SEQLO, .off = _OUT(seqlo), .cb = snl_attr_get_uint32 },
  1507. { .type = PF_STP_SEQHI, .off = _OUT(seqhi), .cb = snl_attr_get_uint32 },
  1508. { .type = PF_STP_SEQDIFF, .off = _OUT(seqdiff), .cb = snl_attr_get_uint32 },
  1509. { .type = PF_STP_STATE, .off = _OUT(state), .cb = snl_attr_get_uint8 },
  1510. { .type = PF_STP_WSCALE, .off = _OUT(wscale), .cb = snl_attr_get_uint8 },
  1511. };
  1512. SNL_DECLARE_ATTR_PARSER(speer_parser, nla_p_speer);
  1513. #undef _OUT
  1514. #define _OUT(_field) offsetof(struct pf_state_key_export, _field)
  1515. static const struct snl_attr_parser nla_p_skey[] = {
  1516. { .type = PF_STK_ADDR0, .off = _OUT(addr[0]), .cb = snl_attr_get_pfaddr },
  1517. { .type = PF_STK_ADDR1, .off = _OUT(addr[1]), .cb = snl_attr_get_pfaddr },
  1518. { .type = PF_STK_PORT0, .off = _OUT(port[0]), .cb = snl_attr_get_uint16 },
  1519. { .type = PF_STK_PORT1, .off = _OUT(port[1]), .cb = snl_attr_get_uint16 },
  1520. };
  1521. SNL_DECLARE_ATTR_PARSER(skey_parser, nla_p_skey);
  1522. #undef _OUT
  1523. #define _IN(_field) offsetof(struct genlmsghdr, _field)
  1524. #define _OUT(_field) offsetof(struct pfctl_state, _field)
  1525. static struct snl_attr_parser ap_state[] = {
  1526. { .type = PF_ST_ID, .off = _OUT(id), .cb = snl_attr_get_uint64 },
  1527. { .type = PF_ST_CREATORID, .off = _OUT(creatorid), .cb = snl_attr_get_uint32 },
  1528. { .type = PF_ST_IFNAME, .off = _OUT(ifname), .cb = snl_attr_store_ifname },
  1529. { .type = PF_ST_ORIG_IFNAME, .off = _OUT(orig_ifname), .cb = snl_attr_store_ifname },
  1530. { .type = PF_ST_KEY_WIRE, .off = _OUT(key[0]), .arg = &skey_parser, .cb = snl_attr_get_nested },
  1531. { .type = PF_ST_KEY_STACK, .off = _OUT(key[1]), .arg = &skey_parser, .cb = snl_attr_get_nested },
  1532. { .type = PF_ST_PEER_SRC, .off = _OUT(src), .arg = &speer_parser, .cb = snl_attr_get_nested },
  1533. { .type = PF_ST_PEER_DST, .off = _OUT(dst), .arg = &speer_parser, .cb = snl_attr_get_nested },
  1534. { .type = PF_ST_RT_ADDR, .off = _OUT(rt_addr), .cb = snl_attr_get_pfaddr },
  1535. { .type = PF_ST_RULE, .off = _OUT(rule), .cb = snl_attr_get_uint32 },
  1536. { .type = PF_ST_ANCHOR, .off = _OUT(anchor), .cb = snl_attr_get_uint32 },
  1537. { .type = PF_ST_NAT_RULE, .off = _OUT(nat_rule), .cb = snl_attr_get_uint32 },
  1538. { .type = PF_ST_CREATION, .off = _OUT(creation), .cb = snl_attr_get_uint32 },
  1539. { .type = PF_ST_EXPIRE, .off = _OUT(expire), .cb = snl_attr_get_uint32 },
  1540. { .type = PF_ST_PACKETS0, .off = _OUT(packets[0]), .cb = snl_attr_get_uint64 },
  1541. { .type = PF_ST_PACKETS1, .off = _OUT(packets[1]), .cb = snl_attr_get_uint64 },
  1542. { .type = PF_ST_BYTES0, .off = _OUT(bytes[0]), .cb = snl_attr_get_uint64 },
  1543. { .type = PF_ST_BYTES1, .off = _OUT(bytes[1]), .cb = snl_attr_get_uint64 },
  1544. { .type = PF_ST_AF, .off = _OUT(key[0].af), .cb = snl_attr_get_uint8 },
  1545. { .type = PF_ST_PROTO, .off = _OUT(key[0].proto), .cb = snl_attr_get_uint8 },
  1546. { .type = PF_ST_DIRECTION, .off = _OUT(direction), .cb = snl_attr_get_uint8 },
  1547. { .type = PF_ST_LOG, .off = _OUT(log), .cb = snl_attr_get_uint8 },
  1548. { .type = PF_ST_STATE_FLAGS, .off = _OUT(state_flags), .cb = snl_attr_get_uint16 },
  1549. { .type = PF_ST_SYNC_FLAGS, .off = _OUT(sync_flags), .cb = snl_attr_get_uint8 },
  1550. { .type = PF_ST_RTABLEID, .off = _OUT(rtableid), .cb = snl_attr_get_int32 },
  1551. { .type = PF_ST_MIN_TTL, .off = _OUT(min_ttl), .cb = snl_attr_get_uint8 },
  1552. { .type = PF_ST_MAX_MSS, .off = _OUT(max_mss), .cb = snl_attr_get_uint16 },
  1553. { .type = PF_ST_DNPIPE, .off = _OUT(dnpipe), .cb = snl_attr_get_uint16 },
  1554. { .type = PF_ST_DNRPIPE, .off = _OUT(dnrpipe), .cb = snl_attr_get_uint16 },
  1555. { .type = PF_ST_RT, .off = _OUT(rt), .cb = snl_attr_get_uint8 },
  1556. { .type = PF_ST_RT_IFNAME, .off = _OUT(rt_ifname), .cb = snl_attr_store_ifname },
  1557. };
  1558. static struct snl_field_parser fp_state[] = {
  1559. };
  1560. #undef _IN
  1561. #undef _OUT
  1562. SNL_DECLARE_PARSER(state_parser, struct genlmsghdr, fp_state, ap_state);
  1563. static const struct snl_hdr_parser *all_parsers[] = {
  1564. &state_parser, &skey_parser, &speer_parser,
  1565. &creator_parser, &getrules_parser
  1566. };
  1567. static int
  1568. pfctl_get_states_nl(struct pfctl_state_filter *filter, struct snl_state *ss, pfctl_get_state_fn f, void *arg)
  1569. {
  1570. SNL_VERIFY_PARSERS(all_parsers);
  1571. int family_id = snl_get_genl_family(ss, PFNL_FAMILY_NAME);
  1572. int ret;
  1573. struct nlmsghdr *hdr;
  1574. struct snl_writer nw;
  1575. if (family_id == 0)
  1576. return (ENOTSUP);
  1577. snl_init_writer(ss, &nw);
  1578. hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GETSTATES);
  1579. hdr->nlmsg_flags |= NLM_F_DUMP;
  1580. snl_add_msg_attr_string(&nw, PF_ST_IFNAME, filter->ifname);
  1581. snl_add_msg_attr_u16(&nw, PF_ST_PROTO, filter->proto);
  1582. snl_add_msg_attr_u8(&nw, PF_ST_AF, filter->af);
  1583. snl_add_msg_attr_ip6(&nw, PF_ST_FILTER_ADDR, &filter->addr.v6);
  1584. snl_add_msg_attr_ip6(&nw, PF_ST_FILTER_MASK, &filter->mask.v6);
  1585. hdr = snl_finalize_msg(&nw);
  1586. if (hdr == NULL)
  1587. return (ENOMEM);
  1588. uint32_t seq_id = hdr->nlmsg_seq;
  1589. snl_send_message(ss, hdr);
  1590. struct snl_errmsg_data e = {};
  1591. while ((hdr = snl_read_reply_multi(ss, seq_id, &e)) != NULL) {
  1592. struct pfctl_state s;
  1593. bzero(&s, sizeof(s));
  1594. if (!snl_parse_nlmsg(ss, hdr, &state_parser, &s))
  1595. continue;
  1596. s.key[1].af = s.key[0].af;
  1597. s.key[1].proto = s.key[0].proto;
  1598. ret = f(&s, arg);
  1599. if (ret != 0)
  1600. return (ret);
  1601. }
  1602. return (0);
  1603. }
  1604. int
  1605. pfctl_get_states_iter(pfctl_get_state_fn f, void *arg)
  1606. {
  1607. struct pfctl_state_filter filter = {};
  1608. return (pfctl_get_filtered_states_iter(&filter, f, arg));
  1609. }
  1610. int
  1611. pfctl_get_filtered_states_iter(struct pfctl_state_filter *filter, pfctl_get_state_fn f, void *arg)
  1612. {
  1613. struct snl_state ss = {};
  1614. int error;
  1615. snl_init(&ss, NETLINK_GENERIC);
  1616. error = pfctl_get_states_nl(filter, &ss, f, arg);
  1617. snl_free(&ss);
  1618. return (error);
  1619. }
  1620. static int
  1621. pfctl_append_states(struct pfctl_state *s, void *arg)
  1622. {
  1623. struct pfctl_state *new;
  1624. struct pfctl_states *states = (struct pfctl_states *)arg;
  1625. new = malloc(sizeof(*s));
  1626. if (new == NULL)
  1627. return (ENOMEM);
  1628. memcpy(new, s, sizeof(*s));
  1629. TAILQ_INSERT_TAIL(&states->states, new, entry);
  1630. return (0);
  1631. }
  1632. int
  1633. pfctl_get_states(int dev __unused, struct pfctl_states *states)
  1634. {
  1635. int ret;
  1636. bzero(states, sizeof(*states));
  1637. TAILQ_INIT(&states->states);
  1638. ret = pfctl_get_states_iter(pfctl_append_states, states);
  1639. if (ret != 0) {
  1640. pfctl_free_states(states);
  1641. return (ret);
  1642. }
  1643. return (0);
  1644. }
  1645. void
  1646. pfctl_free_states(struct pfctl_states *states)
  1647. {
  1648. struct pfctl_state *s, *tmp;
  1649. TAILQ_FOREACH_SAFE(s, &states->states, entry, tmp) {
  1650. free(s);
  1651. }
  1652. bzero(states, sizeof(*states));
  1653. }
  1654. struct pfctl_nl_clear_states {
  1655. uint32_t killed;
  1656. };
  1657. #define _OUT(_field) offsetof(struct pfctl_nl_clear_states, _field)
  1658. static struct snl_attr_parser ap_clear_states[] = {
  1659. { .type = PF_CS_KILLED, .off = _OUT(killed), .cb = snl_attr_get_uint32 },
  1660. };
  1661. static struct snl_field_parser fp_clear_states[] = {};
  1662. #undef _OUT
  1663. SNL_DECLARE_PARSER(clear_states_parser, struct genlmsghdr, fp_clear_states, ap_clear_states);
  1664. static int
  1665. _pfctl_clear_states_h(struct pfctl_handle *h, const struct pfctl_kill *kill,
  1666. unsigned int *killed, int cmd)
  1667. {
  1668. struct snl_writer nw;
  1669. struct snl_errmsg_data e = {};
  1670. struct pfctl_nl_clear_states attrs = {};
  1671. struct nlmsghdr *hdr;
  1672. uint32_t seq_id;
  1673. int family_id;
  1674. family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME);
  1675. if (family_id == 0)
  1676. return (ENOTSUP);
  1677. snl_init_writer(&h->ss, &nw);
  1678. hdr = snl_create_genl_msg_request(&nw, family_id, cmd);
  1679. hdr->nlmsg_flags |= NLM_F_DUMP;
  1680. snl_add_msg_attr_u64(&nw, PF_CS_CMP_ID, kill->cmp.id);
  1681. snl_add_msg_attr_u32(&nw, PF_CS_CMP_CREATORID, htonl(kill->cmp.creatorid));
  1682. snl_add_msg_attr_u8(&nw, PF_CS_CMP_DIR, kill->cmp.direction);
  1683. snl_add_msg_attr_u8(&nw, PF_CS_AF, kill->af);
  1684. snl_add_msg_attr_u8(&nw, PF_CS_PROTO, kill->proto);
  1685. snl_add_msg_attr_rule_addr(&nw, PF_CS_SRC, &kill->src);
  1686. snl_add_msg_attr_rule_addr(&nw, PF_CS_DST, &kill->dst);
  1687. snl_add_msg_attr_rule_addr(&nw, PF_CS_RT_ADDR, &kill->rt_addr);
  1688. snl_add_msg_attr_string(&nw, PF_CS_IFNAME, kill->ifname);
  1689. snl_add_msg_attr_string(&nw, PF_CS_LABEL, kill->label);
  1690. snl_add_msg_attr_bool(&nw, PF_CS_KILL_MATCH, kill->kill_match);
  1691. snl_add_msg_attr_bool(&nw, PF_CS_NAT, kill->nat);
  1692. if ((hdr = snl_finalize_msg(&nw)) == NULL)
  1693. return (ENXIO);
  1694. seq_id = hdr->nlmsg_seq;
  1695. if (! snl_send_message(&h->ss, hdr))
  1696. return (ENXIO);
  1697. while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
  1698. if (! snl_parse_nlmsg(&h->ss, hdr, &clear_states_parser, &attrs))
  1699. continue;
  1700. }
  1701. if (killed)
  1702. *killed = attrs.killed;
  1703. return (e.error);
  1704. }
  1705. int
  1706. pfctl_clear_states_h(struct pfctl_handle *h, const struct pfctl_kill *kill,
  1707. unsigned int *killed)
  1708. {
  1709. return(_pfctl_clear_states_h(h, kill, killed, PFNL_CMD_CLRSTATES));
  1710. }
  1711. int
  1712. pfctl_kill_states_h(struct pfctl_handle *h, const struct pfctl_kill *kill,
  1713. unsigned int *killed)
  1714. {
  1715. return(_pfctl_clear_states_h(h, kill, killed, PFNL_CMD_KILLSTATES));
  1716. }
  1717. static int
  1718. _pfctl_clear_states(int dev __unused, const struct pfctl_kill *kill,
  1719. unsigned int *killed, uint64_t cmd)
  1720. {
  1721. struct pfctl_handle *h;
  1722. int ret;
  1723. h = pfctl_open(PF_DEVICE);
  1724. if (h == NULL)
  1725. return (ENODEV);
  1726. ret = _pfctl_clear_states_h(h, kill, killed, cmd);
  1727. pfctl_close(h);
  1728. return (ret);
  1729. }
  1730. int
  1731. pfctl_clear_states(int dev __unused, const struct pfctl_kill *kill,
  1732. unsigned int *killed)
  1733. {
  1734. return (_pfctl_clear_states(dev, kill, killed, PFNL_CMD_CLRSTATES));
  1735. }
  1736. int
  1737. pfctl_kill_states(int dev __unused, const struct pfctl_kill *kill, unsigned int *killed)
  1738. {
  1739. return (_pfctl_clear_states(dev, kill, killed, PFNL_CMD_KILLSTATES));
  1740. }
  1741. int
  1742. pfctl_clear_rules(int dev, const char *anchorname)
  1743. {
  1744. struct pfioc_trans trans;
  1745. struct pfioc_trans_e transe[2];
  1746. int ret;
  1747. bzero(&trans, sizeof(trans));
  1748. bzero(&transe, sizeof(transe));
  1749. transe[0].rs_num = PF_RULESET_SCRUB;
  1750. if (strlcpy(transe[0].anchor, anchorname, sizeof(transe[0].anchor))
  1751. >= sizeof(transe[0].anchor))
  1752. return (E2BIG);
  1753. transe[1].rs_num = PF_RULESET_FILTER;
  1754. if (strlcpy(transe[1].anchor, anchorname, sizeof(transe[1].anchor))
  1755. >= sizeof(transe[1].anchor))
  1756. return (E2BIG);
  1757. trans.size = 2;
  1758. trans.esize = sizeof(transe[0]);
  1759. trans.array = transe;
  1760. ret = ioctl(dev, DIOCXBEGIN, &trans);
  1761. if (ret != 0)
  1762. return (ret);
  1763. return ioctl(dev, DIOCXCOMMIT, &trans);
  1764. }
  1765. int
  1766. pfctl_clear_nat(int dev, const char *anchorname)
  1767. {
  1768. struct pfioc_trans trans;
  1769. struct pfioc_trans_e transe[3];
  1770. int ret;
  1771. bzero(&trans, sizeof(trans));
  1772. bzero(&transe, sizeof(transe));
  1773. transe[0].rs_num = PF_RULESET_NAT;
  1774. if (strlcpy(transe[0].anchor, anchorname, sizeof(transe[0].anchor))
  1775. >= sizeof(transe[0].anchor))
  1776. return (E2BIG);
  1777. transe[1].rs_num = PF_RULESET_BINAT;
  1778. if (strlcpy(transe[1].anchor, anchorname, sizeof(transe[1].anchor))
  1779. >= sizeof(transe[0].anchor))
  1780. return (E2BIG);
  1781. transe[2].rs_num = PF_RULESET_RDR;
  1782. if (strlcpy(transe[2].anchor, anchorname, sizeof(transe[2].anchor))
  1783. >= sizeof(transe[2].anchor))
  1784. return (E2BIG);
  1785. trans.size = 3;
  1786. trans.esize = sizeof(transe[0]);
  1787. trans.array = transe;
  1788. ret = ioctl(dev, DIOCXBEGIN, &trans);
  1789. if (ret != 0)
  1790. return (ret);
  1791. return ioctl(dev, DIOCXCOMMIT, &trans);
  1792. }
  1793. int
  1794. pfctl_clear_eth_rules(int dev, const char *anchorname)
  1795. {
  1796. struct pfioc_trans trans;
  1797. struct pfioc_trans_e transe;
  1798. int ret;
  1799. bzero(&trans, sizeof(trans));
  1800. bzero(&transe, sizeof(transe));
  1801. transe.rs_num = PF_RULESET_ETH;
  1802. if (strlcpy(transe.anchor, anchorname, sizeof(transe.anchor))
  1803. >= sizeof(transe.anchor))
  1804. return (E2BIG);
  1805. trans.size = 1;
  1806. trans.esize = sizeof(transe);
  1807. trans.array = &transe;
  1808. ret = ioctl(dev, DIOCXBEGIN, &trans);
  1809. if (ret != 0)
  1810. return (ret);
  1811. return ioctl(dev, DIOCXCOMMIT, &trans);
  1812. }
  1813. static int
  1814. _pfctl_get_limit(int dev, const int index, uint *limit)
  1815. {
  1816. struct pfioc_limit pl;
  1817. bzero(&pl, sizeof(pl));
  1818. pl.index = index;
  1819. if (ioctl(dev, DIOCGETLIMIT, &pl) == -1)
  1820. return (errno);
  1821. *limit = pl.limit;
  1822. return (0);
  1823. }
  1824. int
  1825. pfctl_set_syncookies(int dev, const struct pfctl_syncookies *s)
  1826. {
  1827. struct pfioc_nv nv;
  1828. nvlist_t *nvl;
  1829. int ret;
  1830. uint state_limit;
  1831. uint64_t lim, hi, lo;
  1832. ret = _pfctl_get_limit(dev, PF_LIMIT_STATES, &state_limit);
  1833. if (ret != 0)
  1834. return (ret);
  1835. lim = state_limit;
  1836. hi = lim * s->highwater / 100;
  1837. lo = lim * s->lowwater / 100;
  1838. if (lo == hi)
  1839. hi++;
  1840. nvl = nvlist_create(0);
  1841. nvlist_add_bool(nvl, "enabled", s->mode != PFCTL_SYNCOOKIES_NEVER);
  1842. nvlist_add_bool(nvl, "adaptive", s->mode == PFCTL_SYNCOOKIES_ADAPTIVE);
  1843. nvlist_add_number(nvl, "highwater", hi);
  1844. nvlist_add_number(nvl, "lowwater", lo);
  1845. nv.data = nvlist_pack(nvl, &nv.len);
  1846. nv.size = nv.len;
  1847. nvlist_destroy(nvl);
  1848. nvl = NULL;
  1849. ret = ioctl(dev, DIOCSETSYNCOOKIES, &nv);
  1850. free(nv.data);
  1851. return (ret);
  1852. }
  1853. int
  1854. pfctl_get_syncookies(int dev, struct pfctl_syncookies *s)
  1855. {
  1856. nvlist_t *nvl;
  1857. int ret;
  1858. uint state_limit;
  1859. bool enabled, adaptive;
  1860. ret = _pfctl_get_limit(dev, PF_LIMIT_STATES, &state_limit);
  1861. if (ret != 0)
  1862. return (ret);
  1863. bzero(s, sizeof(*s));
  1864. nvl = nvlist_create(0);
  1865. if ((ret = pfctl_do_ioctl(dev, DIOCGETSYNCOOKIES, 256, &nvl)) != 0) {
  1866. ret = errno;
  1867. goto out;
  1868. }
  1869. enabled = nvlist_get_bool(nvl, "enabled");
  1870. adaptive = nvlist_get_bool(nvl, "adaptive");
  1871. if (enabled) {
  1872. if (adaptive)
  1873. s->mode = PFCTL_SYNCOOKIES_ADAPTIVE;
  1874. else
  1875. s->mode = PFCTL_SYNCOOKIES_ALWAYS;
  1876. } else {
  1877. s->mode = PFCTL_SYNCOOKIES_NEVER;
  1878. }
  1879. s->highwater = nvlist_get_number(nvl, "highwater") * 100 / state_limit;
  1880. s->lowwater = nvlist_get_number(nvl, "lowwater") * 100 / state_limit;
  1881. s->halfopen_states = nvlist_get_number(nvl, "halfopen_states");
  1882. out:
  1883. nvlist_destroy(nvl);
  1884. return (ret);
  1885. }
  1886. int
  1887. pfctl_table_add_addrs(int dev, struct pfr_table *tbl, struct pfr_addr
  1888. *addr, int size, int *nadd, int flags)
  1889. {
  1890. struct pfioc_table io;
  1891. if (tbl == NULL || size < 0 || (size && addr == NULL)) {
  1892. return (EINVAL);
  1893. }
  1894. bzero(&io, sizeof io);
  1895. io.pfrio_flags = flags;
  1896. io.pfrio_table = *tbl;
  1897. io.pfrio_buffer = addr;
  1898. io.pfrio_esize = sizeof(*addr);
  1899. io.pfrio_size = size;
  1900. if (ioctl(dev, DIOCRADDADDRS, &io))
  1901. return (errno);
  1902. if (nadd != NULL)
  1903. *nadd = io.pfrio_nadd;
  1904. return (0);
  1905. }
  1906. int
  1907. pfctl_table_del_addrs(int dev, struct pfr_table *tbl, struct pfr_addr
  1908. *addr, int size, int *ndel, int flags)
  1909. {
  1910. struct pfioc_table io;
  1911. if (tbl == NULL || size < 0 || (size && addr == NULL)) {
  1912. return (EINVAL);
  1913. }
  1914. bzero(&io, sizeof io);
  1915. io.pfrio_flags = flags;
  1916. io.pfrio_table = *tbl;
  1917. io.pfrio_buffer = addr;
  1918. io.pfrio_esize = sizeof(*addr);
  1919. io.pfrio_size = size;
  1920. if (ioctl(dev, DIOCRDELADDRS, &io))
  1921. return (errno);
  1922. if (ndel != NULL)
  1923. *ndel = io.pfrio_ndel;
  1924. return (0);
  1925. }
  1926. int
  1927. pfctl_table_set_addrs(int dev, struct pfr_table *tbl, struct pfr_addr
  1928. *addr, int size, int *size2, int *nadd, int *ndel, int *nchange, int flags)
  1929. {
  1930. struct pfioc_table io;
  1931. if (tbl == NULL || size < 0 || (size && addr == NULL)) {
  1932. return (EINVAL);
  1933. }
  1934. bzero(&io, sizeof io);
  1935. io.pfrio_flags = flags;
  1936. io.pfrio_table = *tbl;
  1937. io.pfrio_buffer = addr;
  1938. io.pfrio_esize = sizeof(*addr);
  1939. io.pfrio_size = size;
  1940. io.pfrio_size2 = (size2 != NULL) ? *size2 : 0;
  1941. if (ioctl(dev, DIOCRSETADDRS, &io))
  1942. return (-1);
  1943. if (nadd != NULL)
  1944. *nadd = io.pfrio_nadd;
  1945. if (ndel != NULL)
  1946. *ndel = io.pfrio_ndel;
  1947. if (nchange != NULL)
  1948. *nchange = io.pfrio_nchange;
  1949. if (size2 != NULL)
  1950. *size2 = io.pfrio_size2;
  1951. return (0);
  1952. }
  1953. int pfctl_table_get_addrs(int dev, struct pfr_table *tbl, struct pfr_addr *addr,
  1954. int *size, int flags)
  1955. {
  1956. struct pfioc_table io;
  1957. if (tbl == NULL || size == NULL || *size < 0 ||
  1958. (*size && addr == NULL)) {
  1959. return (EINVAL);
  1960. }
  1961. bzero(&io, sizeof io);
  1962. io.pfrio_flags = flags;
  1963. io.pfrio_table = *tbl;
  1964. io.pfrio_buffer = addr;
  1965. io.pfrio_esize = sizeof(*addr);
  1966. io.pfrio_size = *size;
  1967. if (ioctl(dev, DIOCRGETADDRS, &io))
  1968. return (-1);
  1969. *size = io.pfrio_size;
  1970. return (0);
  1971. }
  1972. int
  1973. pfctl_set_statusif(struct pfctl_handle *h, const char *ifname)
  1974. {
  1975. struct snl_writer nw;
  1976. struct snl_errmsg_data e = {};
  1977. struct nlmsghdr *hdr;
  1978. uint32_t seq_id;
  1979. int family_id;
  1980. family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME);
  1981. if (family_id == 0)
  1982. return (ENOTSUP);
  1983. snl_init_writer(&h->ss, &nw);
  1984. hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_SET_STATUSIF);
  1985. snl_add_msg_attr_string(&nw, PF_SS_IFNAME, ifname);
  1986. if ((hdr = snl_finalize_msg(&nw)) == NULL)
  1987. return (ENXIO);
  1988. seq_id = hdr->nlmsg_seq;
  1989. if (! snl_send_message(&h->ss, hdr))
  1990. return (ENXIO);
  1991. while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
  1992. }
  1993. return (e.error);
  1994. }
  1995. #define _IN(_field) offsetof(struct genlmsghdr, _field)
  1996. #define _OUT(_field) offsetof(struct pfctl_natlook, _field)
  1997. static struct snl_attr_parser ap_natlook[] = {
  1998. { .type = PF_NL_SRC_ADDR, .off = _OUT(saddr), .cb = snl_attr_get_in6_addr },
  1999. { .type = PF_NL_DST_ADDR, .off = _OUT(daddr), .cb = snl_attr_get_in6_addr },
  2000. { .type = PF_NL_SRC_PORT, .off = _OUT(sport), .cb = snl_attr_get_uint16 },
  2001. { .type = PF_NL_DST_PORT, .off = _OUT(dport), .cb = snl_attr_get_uint16 },
  2002. };
  2003. static struct snl_field_parser fp_natlook[] = {};
  2004. #undef _IN
  2005. #undef _OUT
  2006. SNL_DECLARE_PARSER(natlook_parser, struct genlmsghdr, fp_natlook, ap_natlook);
  2007. int
  2008. pfctl_natlook(struct pfctl_handle *h, const struct pfctl_natlook_key *k,
  2009. struct pfctl_natlook *r)
  2010. {
  2011. struct snl_writer nw;
  2012. struct snl_errmsg_data e = {};
  2013. struct nlmsghdr *hdr;
  2014. uint32_t seq_id;
  2015. int family_id;
  2016. family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME);
  2017. if (family_id == 0)
  2018. return (ENOTSUP);
  2019. snl_init_writer(&h->ss, &nw);
  2020. hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_NATLOOK);
  2021. hdr->nlmsg_flags |= NLM_F_DUMP;
  2022. snl_add_msg_attr_u8(&nw, PF_NL_AF, k->af);
  2023. snl_add_msg_attr_u8(&nw, PF_NL_DIRECTION, k->direction);
  2024. snl_add_msg_attr_u8(&nw, PF_NL_PROTO, k->proto);
  2025. snl_add_msg_attr_ip6(&nw, PF_NL_SRC_ADDR, &k->saddr.v6);
  2026. snl_add_msg_attr_ip6(&nw, PF_NL_DST_ADDR, &k->daddr.v6);
  2027. snl_add_msg_attr_u16(&nw, PF_NL_SRC_PORT, k->sport);
  2028. snl_add_msg_attr_u16(&nw, PF_NL_DST_PORT, k->dport);
  2029. if ((hdr = snl_finalize_msg(&nw)) == NULL)
  2030. return (ENXIO);
  2031. seq_id = hdr->nlmsg_seq;
  2032. if (! snl_send_message(&h->ss, hdr))
  2033. return (ENXIO);
  2034. while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
  2035. if (! snl_parse_nlmsg(&h->ss, hdr, &natlook_parser, r))
  2036. continue;
  2037. }
  2038. return (e.error);
  2039. }
  2040. int
  2041. pfctl_set_debug(struct pfctl_handle *h, uint32_t level)
  2042. {
  2043. struct snl_writer nw;
  2044. struct snl_errmsg_data e = {};
  2045. struct nlmsghdr *hdr;
  2046. uint32_t seq_id;
  2047. int family_id;
  2048. family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME);
  2049. if (family_id == 0)
  2050. return (ENOTSUP);
  2051. snl_init_writer(&h->ss, &nw);
  2052. hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_SET_DEBUG);
  2053. snl_add_msg_attr_u32(&nw, PF_SD_LEVEL, level);
  2054. if ((hdr = snl_finalize_msg(&nw)) == NULL)
  2055. return (ENXIO);
  2056. seq_id = hdr->nlmsg_seq;
  2057. if (! snl_send_message(&h->ss, hdr))
  2058. return (ENXIO);
  2059. while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
  2060. }
  2061. return (e.error);
  2062. }
  2063. int
  2064. pfctl_set_timeout(struct pfctl_handle *h, uint32_t timeout, uint32_t seconds)
  2065. {
  2066. struct snl_writer nw;
  2067. struct snl_errmsg_data e = {};
  2068. struct nlmsghdr *hdr;
  2069. uint32_t seq_id;
  2070. int family_id;
  2071. family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME);
  2072. if (family_id == 0)
  2073. return (ENOTSUP);
  2074. snl_init_writer(&h->ss, &nw);
  2075. hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_SET_TIMEOUT);
  2076. snl_add_msg_attr_u32(&nw, PF_TO_TIMEOUT, timeout);
  2077. snl_add_msg_attr_u32(&nw, PF_TO_SECONDS, seconds);
  2078. if ((hdr = snl_finalize_msg(&nw)) == NULL)
  2079. return (ENXIO);
  2080. seq_id = hdr->nlmsg_seq;
  2081. if (! snl_send_message(&h->ss, hdr))
  2082. return (ENXIO);
  2083. while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
  2084. }
  2085. return (e.error);
  2086. }
  2087. struct pfctl_nl_timeout {
  2088. uint32_t seconds;
  2089. };
  2090. #define _OUT(_field) offsetof(struct pfctl_nl_timeout, _field)
  2091. static struct snl_attr_parser ap_get_timeout[] = {
  2092. { .type = PF_TO_SECONDS, .off = _OUT(seconds), .cb = snl_attr_get_uint32 },
  2093. };
  2094. static struct snl_field_parser fp_get_timeout[] = {};
  2095. #undef _OUT
  2096. SNL_DECLARE_PARSER(get_timeout_parser, struct genlmsghdr, fp_get_timeout, ap_get_timeout);
  2097. int
  2098. pfctl_get_timeout(struct pfctl_handle *h, uint32_t timeout, uint32_t *seconds)
  2099. {
  2100. struct snl_writer nw;
  2101. struct pfctl_nl_timeout to = {};
  2102. struct snl_errmsg_data e = {};
  2103. struct nlmsghdr *hdr;
  2104. uint32_t seq_id;
  2105. int family_id;
  2106. family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME);
  2107. if (family_id == 0)
  2108. return (ENOTSUP);
  2109. snl_init_writer(&h->ss, &nw);
  2110. hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GET_TIMEOUT);
  2111. hdr->nlmsg_flags |= NLM_F_DUMP;
  2112. snl_add_msg_attr_u32(&nw, PF_TO_TIMEOUT, timeout);
  2113. if ((hdr = snl_finalize_msg(&nw)) == NULL)
  2114. return (ENXIO);
  2115. seq_id = hdr->nlmsg_seq;
  2116. if (! snl_send_message(&h->ss, hdr))
  2117. return (ENXIO);
  2118. while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
  2119. if (! snl_parse_nlmsg(&h->ss, hdr, &get_timeout_parser, &to))
  2120. continue;
  2121. }
  2122. if (seconds != NULL)
  2123. *seconds = to.seconds;
  2124. return (e.error);
  2125. }
  2126. int
  2127. pfctl_set_limit(struct pfctl_handle *h, const int index, const uint limit)
  2128. {
  2129. struct snl_writer nw;
  2130. struct snl_errmsg_data e = {};
  2131. struct nlmsghdr *hdr;
  2132. uint32_t seq_id;
  2133. int family_id;
  2134. family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME);
  2135. if (family_id == 0)
  2136. return (ENOTSUP);
  2137. snl_init_writer(&h->ss, &nw);
  2138. hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_SET_LIMIT);
  2139. snl_add_msg_attr_u32(&nw, PF_LI_INDEX, index);
  2140. snl_add_msg_attr_u32(&nw, PF_LI_LIMIT, limit);
  2141. if ((hdr = snl_finalize_msg(&nw)) == NULL)
  2142. return (ENXIO);
  2143. seq_id = hdr->nlmsg_seq;
  2144. if (! snl_send_message(&h->ss, hdr))
  2145. return (ENXIO);
  2146. while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
  2147. }
  2148. return (e.error);
  2149. }
  2150. struct pfctl_nl_limit {
  2151. unsigned int limit;
  2152. };
  2153. #define _OUT(_field) offsetof(struct pfctl_nl_limit, _field)
  2154. static struct snl_attr_parser ap_get_limit[] = {
  2155. { .type = PF_LI_LIMIT, .off = _OUT(limit), .cb = snl_attr_get_uint32 },
  2156. };
  2157. static struct snl_field_parser fp_get_limit[] = {};
  2158. #undef _OUT
  2159. SNL_DECLARE_PARSER(get_limit_parser, struct genlmsghdr, fp_get_limit, ap_get_limit);
  2160. int
  2161. pfctl_get_limit(struct pfctl_handle *h, const int index, uint *limit)
  2162. {
  2163. struct snl_writer nw;
  2164. struct pfctl_nl_limit li = {};
  2165. struct snl_errmsg_data e = {};
  2166. struct nlmsghdr *hdr;
  2167. uint32_t seq_id;
  2168. int family_id;
  2169. family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME);
  2170. if (family_id == 0)
  2171. return (ENOTSUP);
  2172. snl_init_writer(&h->ss, &nw);
  2173. hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GET_LIMIT);
  2174. hdr->nlmsg_flags |= NLM_F_DUMP;
  2175. snl_add_msg_attr_u32(&nw, PF_LI_INDEX, index);
  2176. if ((hdr = snl_finalize_msg(&nw)) == NULL)
  2177. return (ENXIO);
  2178. seq_id = hdr->nlmsg_seq;
  2179. if (! snl_send_message(&h->ss, hdr))
  2180. return (ENXIO);
  2181. while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
  2182. if (! snl_parse_nlmsg(&h->ss, hdr, &get_limit_parser, &li))
  2183. continue;
  2184. }
  2185. if (limit != NULL)
  2186. *limit = li.limit;
  2187. return (e.error);
  2188. }
  2189. struct pfctl_nl_begin_addrs {
  2190. uint32_t ticket;
  2191. };
  2192. #define _OUT(_field) offsetof(struct pfctl_nl_begin_addrs, _field)
  2193. static struct snl_attr_parser ap_begin_addrs[] = {
  2194. { .type = PF_BA_TICKET, .off = _OUT(ticket), .cb = snl_attr_get_uint32 },
  2195. };
  2196. static struct snl_field_parser fp_begin_addrs[] = {};
  2197. #undef _OUT
  2198. SNL_DECLARE_PARSER(begin_addrs_parser, struct genlmsghdr, fp_begin_addrs, ap_begin_addrs);
  2199. int
  2200. pfctl_begin_addrs(struct pfctl_handle *h, uint32_t *ticket)
  2201. {
  2202. struct snl_writer nw;
  2203. struct pfctl_nl_begin_addrs attrs = {};
  2204. struct snl_errmsg_data e = {};
  2205. struct nlmsghdr *hdr;
  2206. uint32_t seq_id;
  2207. int family_id;
  2208. family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME);
  2209. if (family_id == 0)
  2210. return (ENOTSUP);
  2211. snl_init_writer(&h->ss, &nw);
  2212. hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_BEGIN_ADDRS);
  2213. hdr->nlmsg_flags |= NLM_F_DUMP;
  2214. if ((hdr = snl_finalize_msg(&nw)) == NULL)
  2215. return (ENXIO);
  2216. seq_id = hdr->nlmsg_seq;
  2217. if (! snl_send_message(&h->ss, hdr))
  2218. return (ENXIO);
  2219. while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
  2220. if (! snl_parse_nlmsg(&h->ss, hdr, &begin_addrs_parser, &attrs))
  2221. continue;
  2222. }
  2223. if (ticket != NULL)
  2224. *ticket = attrs.ticket;
  2225. return (e.error);
  2226. }
  2227. int
  2228. pfctl_add_addr(struct pfctl_handle *h, const struct pfioc_pooladdr *pa)
  2229. {
  2230. struct snl_writer nw;
  2231. struct snl_errmsg_data e = {};
  2232. struct nlmsghdr *hdr;
  2233. uint32_t seq_id;
  2234. int family_id;
  2235. family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME);
  2236. if (family_id == 0)
  2237. return (ENOTSUP);
  2238. snl_init_writer(&h->ss, &nw);
  2239. hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_ADD_ADDR);
  2240. snl_add_msg_attr_u32(&nw, PF_AA_ACTION, pa->action);
  2241. snl_add_msg_attr_u32(&nw, PF_AA_TICKET, pa->ticket);
  2242. snl_add_msg_attr_u32(&nw, PF_AA_NR, pa->nr);
  2243. snl_add_msg_attr_u32(&nw, PF_AA_R_NUM, pa->r_num);
  2244. snl_add_msg_attr_u8(&nw, PF_AA_R_ACTION, pa->r_action);
  2245. snl_add_msg_attr_u8(&nw, PF_AA_R_LAST, pa->r_last);
  2246. snl_add_msg_attr_u8(&nw, PF_AA_AF, pa->af);
  2247. snl_add_msg_attr_string(&nw, PF_AA_ANCHOR, pa->anchor);
  2248. snl_add_msg_attr_pool_addr(&nw, PF_AA_ADDR, &pa->addr);
  2249. if ((hdr = snl_finalize_msg(&nw)) == NULL)
  2250. return (ENXIO);
  2251. seq_id = hdr->nlmsg_seq;
  2252. if (! snl_send_message(&h->ss, hdr))
  2253. return (ENXIO);
  2254. while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
  2255. }
  2256. return (e.error);
  2257. }
  2258. static const struct snl_attr_parser ap_get_addrs[] = {
  2259. { .type = PF_AA_NR, .off = 0, .cb = snl_attr_get_uint32 },
  2260. };
  2261. static struct snl_field_parser fp_get_addrs[] = {};
  2262. SNL_DECLARE_PARSER(get_addrs_parser, struct genlmsghdr, fp_get_addrs, ap_get_addrs);
  2263. int
  2264. pfctl_get_addrs(struct pfctl_handle *h, uint32_t ticket, uint32_t r_num,
  2265. uint8_t r_action, const char *anchor, uint32_t *nr)
  2266. {
  2267. struct snl_writer nw;
  2268. struct snl_errmsg_data e = {};
  2269. struct nlmsghdr *hdr;
  2270. uint32_t seq_id;
  2271. int family_id;
  2272. family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME);
  2273. if (family_id == 0)
  2274. return (ENOTSUP);
  2275. snl_init_writer(&h->ss, &nw);
  2276. hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GET_ADDRS);
  2277. snl_add_msg_attr_u32(&nw, PF_AA_TICKET, ticket);
  2278. snl_add_msg_attr_u32(&nw, PF_AA_R_NUM, r_num);
  2279. snl_add_msg_attr_u8(&nw, PF_AA_R_ACTION, r_action);
  2280. snl_add_msg_attr_string(&nw, PF_AA_ANCHOR, anchor);
  2281. if ((hdr = snl_finalize_msg(&nw)) == NULL)
  2282. return (ENXIO);
  2283. seq_id = hdr->nlmsg_seq;
  2284. if (! snl_send_message(&h->ss, hdr))
  2285. return (ENXIO);
  2286. while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
  2287. if (! snl_parse_nlmsg(&h->ss, hdr, &get_addrs_parser, nr))
  2288. continue;
  2289. }
  2290. return (e.error);
  2291. }
  2292. #define _OUT(_field) offsetof(struct pf_pooladdr, _field)
  2293. static const struct snl_attr_parser ap_pool_addr[] = {
  2294. { .type = PF_PA_ADDR, .off = _OUT(addr), .arg = &addr_wrap_parser, .cb = snl_attr_get_nested },
  2295. { .type = PF_PA_IFNAME, .off = _OUT(ifname), .arg_u32 = IFNAMSIZ, .cb = snl_attr_copy_string },
  2296. };
  2297. SNL_DECLARE_ATTR_PARSER(pool_addr_parser, ap_pool_addr);
  2298. #undef _OUT
  2299. #define _OUT(_field) offsetof(struct pfioc_pooladdr, _field)
  2300. static const struct snl_attr_parser ap_get_addr[] = {
  2301. { .type = PF_AA_ACTION, .off = _OUT(action), .cb = snl_attr_get_uint32 },
  2302. { .type = PF_AA_TICKET, .off = _OUT(ticket), .cb = snl_attr_get_uint32 },
  2303. { .type = PF_AA_NR, .off = _OUT(nr), .cb = snl_attr_get_uint32 },
  2304. { .type = PF_AA_R_NUM, .off = _OUT(r_num), .cb = snl_attr_get_uint32 },
  2305. { .type = PF_AA_R_ACTION, .off = _OUT(r_action), .cb = snl_attr_get_uint8 },
  2306. { .type = PF_AA_R_LAST, .off = _OUT(r_last), .cb = snl_attr_get_uint8 },
  2307. { .type = PF_AA_AF, .off = _OUT(af), .cb = snl_attr_get_uint8 },
  2308. { .type = PF_AA_ANCHOR, .off = _OUT(anchor), .arg_u32 = MAXPATHLEN, .cb = snl_attr_copy_string },
  2309. { .type = PF_AA_ADDR, .off = _OUT(addr), .arg = &pool_addr_parser, .cb = snl_attr_get_nested },
  2310. };
  2311. static struct snl_field_parser fp_get_addr[] = {};
  2312. SNL_DECLARE_PARSER(get_addr_parser, struct genlmsghdr, fp_get_addr, ap_get_addr);
  2313. #undef _OUT
  2314. int
  2315. pfctl_get_addr(struct pfctl_handle *h, uint32_t ticket, uint32_t r_num,
  2316. uint8_t r_action, const char *anchor, uint32_t nr, struct pfioc_pooladdr *pa)
  2317. {
  2318. struct snl_writer nw;
  2319. struct snl_errmsg_data e = {};
  2320. struct nlmsghdr *hdr;
  2321. uint32_t seq_id;
  2322. int family_id;
  2323. family_id =snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME);
  2324. if (family_id == 0)
  2325. return (ENOTSUP);
  2326. snl_init_writer(&h->ss, &nw);
  2327. hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GET_ADDR);
  2328. snl_add_msg_attr_u32(&nw, PF_AA_TICKET, ticket);
  2329. snl_add_msg_attr_u32(&nw, PF_AA_R_NUM, r_num);
  2330. snl_add_msg_attr_u8(&nw, PF_AA_R_ACTION, r_action);
  2331. snl_add_msg_attr_string(&nw, PF_AA_ANCHOR, anchor);
  2332. snl_add_msg_attr_u32(&nw, PF_AA_NR, nr);
  2333. if ((hdr = snl_finalize_msg(&nw)) == NULL)
  2334. return (ENXIO);
  2335. seq_id = hdr->nlmsg_seq;
  2336. if (! snl_send_message(&h->ss, hdr))
  2337. return (ENXIO);
  2338. while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
  2339. if (! snl_parse_nlmsg(&h->ss, hdr, &get_addr_parser, pa))
  2340. continue;
  2341. }
  2342. return (0);
  2343. }