├── AUTHORS ├── COPYING ├── Makefile ├── NEWS ├── README ├── contrib ├── PKGBUILD.in ├── bash-completion ├── netctl.install └── zsh-completion ├── docs ├── Makefile ├── examples │ ├── bonding │ ├── bridge │ ├── ethernet-custom │ ├── ethernet-dhcp │ ├── ethernet-static │ ├── macvlan-dhcp │ ├── macvlan-static │ ├── mobile_ppp │ ├── openvswitch │ ├── pppoe │ ├── tunnel │ ├── tuntap │ ├── vlan-dhcp │ ├── vlan-static │ ├── wireguard │ ├── wireless-open │ ├── wireless-wep │ ├── wireless-wpa │ ├── wireless-wpa-config │ ├── wireless-wpa-configsection │ └── wireless-wpa-static ├── netctl-auto.1.txt ├── netctl.1.txt ├── netctl.profile.5.txt ├── netctl.special.7.txt └── wifi-menu.1.txt ├── services ├── netctl-auto@.service ├── netctl-ifplugd@.service ├── netctl-sleep.service ├── netctl-wait-online.service ├── netctl.service └── netctl@.service └── src ├── ifplugd.action ├── lib ├── auto.action ├── connections │ ├── README │ ├── bond │ ├── bridge │ ├── dummy │ ├── ethernet │ ├── macvlan │ ├── mobile_ppp │ ├── openvswitch │ ├── ppp │ ├── pppoe │ ├── tunnel │ ├── tuntap │ ├── vlan │ ├── wireguard │ └── wireless ├── dhcp │ ├── README │ ├── dhclient │ └── dhcpcd ├── globals ├── interface ├── ip ├── network ├── rfkill └── wpa ├── netctl-auto ├── netctl.in └── wifi-menu /AUTHORS: -------------------------------------------------------------------------------- 1 | James Rayner 2 | Jim Pryor 3 | Thomas Bächler 4 | Rémy Oudompheng 5 | Jouke Witteveen 6 | 7 | and many others (try: git shortlog -s) 8 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | export VERSION = 1.29 2 | 3 | PKG_CONFIG ?= pkg-config 4 | 5 | SHELL=/bin/bash 6 | 7 | sd_var = $(shell $(PKG_CONFIG) --variable=systemd$(1) systemd) 8 | systemdsystemconfdir = $(call sd_var,systemconfdir) 9 | systemdsystemunitdir = $(call sd_var,systemunitdir) 10 | 11 | .PHONY: install tarball pkgbuild upload clean 12 | 13 | install: 14 | # Documentation 15 | $(MAKE) -C docs install 16 | # Configuration files 17 | install -d $(DESTDIR)/etc/netctl/{examples,hooks,interfaces} 18 | install -m644 docs/examples/* $(DESTDIR)/etc/netctl/examples/ 19 | # Libs 20 | install -Dt $(DESTDIR)/usr/lib/netctl -m644 src/lib/{globals,interface,ip,rfkill,wpa} 21 | install -Dt $(DESTDIR)/usr/lib/netctl/connections -m644 src/lib/connections/* 22 | install -Dt $(DESTDIR)/usr/lib/netctl/dhcp -m644 src/lib/dhcp/* 23 | install -m755 src/lib/{auto.action,network} $(DESTDIR)/usr/lib/netctl/ 24 | # Scripts 25 | install -d $(DESTDIR)/usr/bin 26 | sed -e "s|@systemdsystemconfdir@|$(systemdsystemconfdir)|g" \ 27 | -e "s|@systemdsystemunitdir@|$(systemdsystemunitdir)|g" \ 28 | src/netctl.in > $(DESTDIR)/usr/bin/netctl 29 | chmod 755 $(DESTDIR)/usr/bin/netctl 30 | install -m755 \ 31 | src/netctl-auto \ 32 | src/wifi-menu \ 33 | $(DESTDIR)/usr/bin/ 34 | install -Dm755 src/ifplugd.action $(DESTDIR)/etc/ifplugd/netctl.action 35 | # Services 36 | install -Dt $(DESTDIR)$(systemdsystemunitdir) -m644 services/*.service 37 | 38 | tarball: netctl-$(VERSION).tar.xz 39 | netctl-$(VERSION).tar.xz: 40 | $(MAKE) -B -C docs 41 | cp src/lib/globals{,.orig} 42 | sed -i "s|NETCTL_VERSION=.*|NETCTL_VERSION=$(VERSION)|" src/lib/globals 43 | git stash save -q 44 | git archive -o netctl-$(VERSION).tar --prefix=netctl-$(VERSION)/ stash 45 | git stash pop -q 46 | mv src/lib/globals{.orig,} 47 | tar --exclude-vcs --transform "s|^|netctl-$(VERSION)/|" --owner=root --group=root --mtime=./netctl-$(VERSION).tar -rf netctl-$(VERSION).tar docs/*.[1-8] 48 | xz netctl-$(VERSION).tar 49 | gpg --detach-sign $@ 50 | 51 | pkgbuild: PKGBUILD 52 | PKGBUILD: netctl-$(VERSION).tar.xz netctl.install contrib/PKGBUILD.in 53 | sed -e "s|@pkgver@|$(VERSION)|g" \ 54 | -e "s|@sha256sum@|$(shell sha256sum $< | cut -d ' ' -f 1)|" \ 55 | $(lastword $^) > $@ 56 | 57 | netctl.install: contrib/netctl.install 58 | cp $< $@ 59 | 60 | upload: netctl-$(VERSION).tar.xz 61 | scp $< $<.sig sources.archlinux.org:/srv/ftp/other/packages/netctl 62 | 63 | clean: 64 | $(MAKE) -C docs clean 65 | -@rm -vf netctl-*.tar.xz{,.sig} PKGBUILD netctl.install 66 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | netctl 1.29 2 | - Support ppp>=2.5.0 3 | - Document bundled DHCP client-specific options 4 | 5 | netctl 1.28 6 | - Support WPA3-Personal security 7 | 8 | netctl 1.27 9 | - Restore connection failure detection in wifi-menu 10 | 11 | netctl 1.26 12 | - Make wireless connections reach network.target earlier 13 | 14 | netctl 1.25 15 | - Support profiles that use hooks in netctl-auto 16 | - Add verify subcommand to netctl 17 | 18 | netctl 1.24 19 | - Fix netctl-ifplugd for interfaces that use DHCP and disappear briefly 20 | - Add man page for wifi-menu 21 | 22 | netctl 1.23 23 | - Update dhcpcd support for dhcpcd 9 24 | 25 | netctl 1.22 26 | - Add rfkill support to mobile_ppp connections 27 | - Improve active interface finding in netctl-auto 28 | 29 | netctl 1.21 30 | - Add support for wireguard interfaces 31 | - Support custom MAC addresses on dynamic interfaces 32 | 33 | netctl 1.20 34 | - Accept router advertisements more often 35 | - Switch from wpa_actiond to using wpa_cli 36 | 37 | netctl 1.19 38 | - Support removable devices in automatic profile handling 39 | - Add "noipdefault" option to mobile_ppp connections 40 | 41 | netctl 1.18 42 | - Move from .include based to drop-in directory based systemd units 43 | - Allow hooks to alter the profile name 44 | 45 | netctl 1.17 46 | - Add support for UTF-8 encoded SSIDs in wifi-menu 47 | - Expose the current command (start/stop) to hooks 48 | 49 | netctl 1.16 50 | - Fix handling of After= 51 | - Update documentation 52 | 53 | netctl 1.15 54 | - Fix clean up of DNS configuration for PPP connections 55 | 56 | netctl 1.14 57 | - Modified hostname handling to only touch the transient hostname 58 | - Add support for custom SYSCFG lines in mobile_ppp profiles 59 | - Improved handling of whitespace in profile names 60 | 61 | netctl 1.13 62 | - Add netctl-wait-online service, fixing the network{,-online}.target logic 63 | - Add wait-online subcommand to netctl and WaitOnline option to profiles 64 | - Improved clean up for wireless connections 65 | - DhcpcdOptions= defaults to "-L", which is no longer added unconditionally 66 | - Minor functional and cosmetic improvements 67 | 68 | netctl 1.12 69 | - Add is-active subcommand to netctl and netctl-auto 70 | - Fix support for profile names with spaces in wifi-menu 71 | 72 | netctl 1.11 73 | - Fix wifi scanning for compatibility with wpa_supplicant 2.4 74 | - Fixes and improvements to mobile_ppp 75 | - Minor functional and cosmetic improvements 76 | 77 | netctl 1.10 78 | - Improved support for automatic selection of wired profiles 79 | - Add edit subcommand to netctl 80 | - Assorted minor fixes 81 | 82 | netctl 1.9 83 | - Add support for openvswitch interfaces 84 | - Improved IPv6 support 85 | 86 | netctl 1.8 87 | - Support for IPv6 with dhcpcd 6.4.0 88 | - Fixes to modes of created files 89 | 90 | netctl 1.7 91 | - Fixes for compatibility with Bash 4.3 92 | - Fix killing of pppd 93 | - Add is-enabled subcommand to netctl 94 | - Add Frequency parameter to WPA configuration 95 | 96 | netctl 1.6 97 | - Fixes for bugs introduced in 1.5 98 | 99 | netctl 1.5 100 | - Add support for macvlan interfaces 101 | - Add option to skip Duplicate Address Detection 102 | - Add support for hooks for dynamic interfaces 103 | - Assorted fixes and improvements 104 | 105 | netctl 1.4 106 | - Add support for dummy interfaces 107 | - Add support for limiting the wireless frequencies to scan 108 | - Add support for custom options files for PPP connections 109 | - Change umask to 077, and the default DHCP timeout to 30 seconds 110 | - Assorted fixes, including fixes to tunnel connections and WEP key handling 111 | 112 | netctl 1.3 113 | - Add real functionality to automatic profile handling (netctl-auto) 114 | - Switch to iproute2 for bridge connections 115 | 116 | netctl 1.2 117 | - Fixes to the logic of IP setup 118 | - Fix default interface bindings 119 | 120 | netctl 1.1 121 | - Add netctl-auto support to wifi-menu 122 | - Use pkg-config to obtain installation paths 123 | - Assorted fixes, including to array handling and calling dhcpcd for IPv4 124 | 125 | netctl 1.0 126 | - Add support for mobile broadband (mobile_ppp) connections 127 | - Update documentation 128 | - Assorted minor fixes 129 | 130 | netctl 0.8 131 | - Fix escaping of unfortunate strings 132 | - Add support for configuration defaults to connection scripts 133 | 134 | netctl 0.7 135 | - Add support for systemd character escaping 136 | - Assorted fixes, including to vlan connections and the documentation 137 | 138 | netctl 0.6 139 | - Add a sleep hook 140 | - Assorted fixes, including fixes to rfkill and the documentation 141 | - Sources are signed for packaging 142 | 143 | netctl 0.5 144 | - Move the configuration directory to /etc/netctl 145 | 146 | netctl 0.4 147 | - Remove default IPv4 netmask 148 | - Add zsh completion 149 | 150 | netctl 0.3 151 | - Correctly wait for devices on boot 152 | - Use the first available network interface by default in wifi-menu 153 | - Suppress ifplugd beep 154 | 155 | netctl 0.2 156 | - Drop the Scan parameter for wireless networking 157 | - Assorted fixes for bugs introduced by forking 158 | 159 | netctl 0.1 160 | - Forked from netcfg 3.1 and changed considerably 161 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Dependencies: 2 | - systemd 3 | - Bash 4.x 4 | - GNU Coreutils 5 | - iproute2 6 | - resolvconf 7 | 8 | Optional: 9 | - dhcpcd or dhclient: for DHCP support 10 | - wpa_supplicant: for WPA support 11 | - dialog: for the interactive assistant 12 | - ifplugd: for automatic wired connections 13 | - ppp: for PPP support 14 | - wireguard-tools: for WireGuard support 15 | 16 | For documentation generation: 17 | - asciidoc 18 | 19 | Naming Conventions for Variables: 20 | end-user variables - CamelCase 21 | local variables - lower_case 22 | other variables - UPPER_CASE 23 | -------------------------------------------------------------------------------- /contrib/PKGBUILD.in: -------------------------------------------------------------------------------- 1 | # Maintainer: Jouke Witteveen 2 | 3 | pkgname=netctl 4 | pkgver=@pkgver@ 5 | pkgrel=1 6 | pkgdesc='Profile based systemd network management' 7 | url='https://gitlab.archlinux.org/archlinux/netctl' 8 | license=('GPL') 9 | depends=('coreutils' 'iproute2' 'resolvconf' 'systemd>=233') 10 | # The source tarball includes pre-built (using asciidoc) documentation. 11 | makedepends=('pkg-config') 12 | optdepends=('dialog: for the menu based wifi assistant' 13 | 'dhclient: for DHCP support (or dhcpcd)' 14 | 'dhcpcd: for DHCP support (or dhclient)' 15 | 'wpa_supplicant: for wireless networking support' 16 | 'ifplugd: for automatic wired connections through netctl-ifplugd' 17 | 'ppp: for PPP connections' 18 | 'openvswitch: for Open vSwitch connections' 19 | 'wireguard-tools: for WireGuard connections') 20 | install=netctl.install 21 | source=(https://sources.archlinux.org/other/packages/netctl/netctl-${pkgver}.tar.xz{,.sig}) 22 | arch=('any') 23 | sha256sums=('@sha256sum@' 24 | 'SKIP') 25 | validpgpkeys=('CFA6AF15E5C74149FC1D8C086D1655C14CE1C13E') # Florian Pritz 26 | 27 | package() { 28 | cd "$srcdir/netctl-${pkgver}" 29 | make DESTDIR="$pkgdir" install 30 | 31 | # Shell Completion 32 | install -D -m644 contrib/bash-completion "$pkgdir/usr/share/bash-completion/completions/netctl" 33 | ln -s netctl "$pkgdir/usr/share/bash-completion/completions/netctl-auto" 34 | ln -s netctl "$pkgdir/usr/share/bash-completion/completions/wifi-menu" 35 | install -D -m644 contrib/zsh-completion "$pkgdir/usr/share/zsh/site-functions/_netctl" 36 | } 37 | 38 | -------------------------------------------------------------------------------- /contrib/bash-completion: -------------------------------------------------------------------------------- 1 | # netctl completion 2 | 3 | 4 | _wireless_interfaces() { 5 | local iface 6 | 7 | for iface in /sys/class/net/*/wireless/; do 8 | echo ${iface:15:-10} 9 | done 10 | } 11 | 12 | 13 | _netctl_profiles() { 14 | find -L /etc/netctl -maxdepth 1 -type f -not -name '.*' -not -name '*~' -not -name $'*\n*' -not -name '*.action' -not -name '*.conf' -not -name '*.service' -printf '%f\n' 15 | } 16 | 17 | 18 | _netctl() { 19 | local cur=${COMP_WORDS[COMP_CWORD]} 20 | 21 | case $COMP_CWORD in 22 | 1) 23 | COMPREPLY=( $(compgen -W "--help --version list store restore stop-all start stop restart switch-to is-active status enable disable reenable is-enabled edit wait-online" -- "$cur") ) 24 | ;; 25 | 2) 26 | [[ ${COMP_WORDS[COMP_CWORD-1]} = @(start|stop|restart|switch-to|is-active|status|enable|disable|reenable|is-enabled|edit|wait-online) ]] && 27 | compopt -o filenames && 28 | mapfile -t COMPREPLY < <(IFS=$'\n'; compgen -W "$(_netctl_profiles)" -- "$cur") 29 | ;; 30 | esac 31 | } 32 | complete -F _netctl netctl 33 | 34 | 35 | _netctl_auto() { 36 | local cur=${COMP_WORDS[COMP_CWORD]} 37 | 38 | case $COMP_CWORD in 39 | 1) 40 | COMPREPLY=( $(compgen -W "--help --version list switch-to is-active enable disable enable-all disable-all is-enabled" -- "$cur") ) 41 | ;; 42 | 2) 43 | [[ ${COMP_WORDS[COMP_CWORD-1]} = @(switch-to|is-active|enable|disable|is-enabled) ]] && 44 | compopt -o filenames && 45 | mapfile -t COMPREPLY < <(IFS=$'\n'; compgen -W "$(_netctl_profiles)" -- "$cur") 46 | ;; 47 | esac 48 | } 49 | complete -F _netctl_auto netctl-auto 50 | 51 | 52 | _wifi_menu() { 53 | (( COMP_CWORD == 1 )) && 54 | COMPREPLY=( $(compgen -W "$(_wireless_interfaces)" -- "${COMP_WORDS[1]}") ) 55 | } 56 | complete -F _wifi_menu wifi-menu 57 | 58 | 59 | # ex: ts=4 sw=4 et filetype=sh 60 | -------------------------------------------------------------------------------- /contrib/netctl.install: -------------------------------------------------------------------------------- 1 | post_upgrade() { 2 | if [[ $(vercmp 1.18 "$2") -gt 0 ]]; then 3 | grep -ls '^.include ' /etc/systemd/system/netctl@*.service | \ 4 | while read -r unit; do 5 | profile=$(systemd-escape --unescape "${unit:27:-8}") 6 | echo ":: The unit for profile '$profile' uses deprecated features." 7 | echo " Consider running: netctl reenable $(printf '%q' "$profile")" 8 | done 9 | fi 10 | } 11 | -------------------------------------------------------------------------------- /contrib/zsh-completion: -------------------------------------------------------------------------------- 1 | #compdef netctl netctl-auto wifi-menu 2 | 3 | 4 | (( $+function[_wireless_interfaces] )) || 5 | _wireless_interfaces() { 6 | local interfaces 7 | interfaces=(/sys/class/net/*/wireless(/)) 8 | print -l ${${(R)interfaces%/wireless}:t} 9 | } 10 | 11 | 12 | (( $+function[_netctl_command] )) || 13 | _netctl_command() { 14 | [[ $words[1] = (start|stop|restart|switch-to|is-active|status|enable|disable|reenable|is-enabled|edit|wait-online) ]] && 15 | compadd "${(f)$(find -L /etc/netctl -maxdepth 1 -type f -not -name '.*' -not -name '*~' -not -name $'*\n*' -not -name '*.action' -not -name '*.conf' -not -name '*.service' -printf '%f\n')}" 16 | } 17 | 18 | 19 | _netctl_commands() { 20 | local -a _commands 21 | _commands=( 22 | 'list:List available profiles' 23 | 'store:Save which profiles are active' 24 | 'restore:Load saved profiles' 25 | 'stop-all:Stops all profiles' 26 | 'start:Start a profile' 27 | 'stop:Stop a profile' 28 | 'restart:Restart a profile' 29 | 'switch-to:Switch to a profile' 30 | 'is-active:Check whether a profile is active' 31 | 'status:Show runtime status of a profile' 32 | 'enable:Enable the systemd unit for a profile' 33 | 'disable:Disable the systemd unit for a profile' 34 | 'reenable:Reenable the systemd unit for a profile' 35 | 'is-enabled:Check whether a profile is enabled' 36 | 'edit:Edit a profile' 37 | 'wait-online:Wait for a profile to finish connecting' 38 | ) 39 | _describe "netctl commands" _commands 40 | } 41 | 42 | _netctl-auto_commands() { 43 | local -a _commands 44 | _commands=( 45 | 'list:List available profiles' 46 | 'switch-to:Switch to a profile, enable it if necessary' 47 | 'is-active:Check whether a profile is active' 48 | 'enable:Enable a profile for automatic selection' 49 | 'disable:Disable a profile temporarily for automatic selection' 50 | 'enable-all:Enable all profiles for automatic selection' 51 | 'disable-all:Disable all profiles temporarily for automatic selection' 52 | 'is-enabled:Check whether a profile is enabled' 53 | ) 54 | _describe "netctl-auto commands" _commands 55 | } 56 | 57 | case $service in 58 | netctl|netctl-auto) 59 | case $CURRENT in 60 | 2) 61 | _arguments \ 62 | '(- :)--version[display version information]' \ 63 | '(- :)--help[display help message]' \ 64 | '(-)::netctl commands:_${service}_commands' 65 | ;; 66 | 3) 67 | shift words 68 | [[ $words[1] != -* ]] && 69 | curcontext="${curcontext%:*}-${words[1]}:" _netctl_command 70 | ;; 71 | esac 72 | ;; 73 | wifi-menu) 74 | (( CURRENT == 2 )) && compadd "${(f)$(_wireless_interfaces)}" 75 | ;; 76 | esac 77 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for netctl documentation 2 | 3 | MANPAGES = netctl.1 netctl-auto.1 netctl.profile.5 netctl.special.7 wifi-menu.1 4 | 5 | .PHONY: manpages install $(MANPAGES:=-install) clean 6 | 7 | manpages: $(MANPAGES) 8 | $(MANPAGES): %: %.txt 9 | a2x -d manpage -f manpage -a manversion=$(VERSION) $< 10 | 11 | install: $(MANPAGES:=-install) 12 | $(MANPAGES:=-install): %-install: % 13 | install -Dm644 $< $(DESTDIR)/usr/share/man/man$(subst .,,$(suffix $<))/$< 14 | 15 | clean: 16 | -@rm -vf $(MANPAGES) 17 | 18 | -------------------------------------------------------------------------------- /docs/examples/bonding: -------------------------------------------------------------------------------- 1 | Description="A bonded interface" 2 | Interface=bond0 3 | Connection=bond 4 | BindsToInterfaces=(eth0 eth2) 5 | IP=static 6 | Address="10.0.0.1/8" 7 | #Mode=balance-rr 8 | -------------------------------------------------------------------------------- /docs/examples/bridge: -------------------------------------------------------------------------------- 1 | Description="Example Bridge connection" 2 | Interface=br0 3 | Connection=bridge 4 | BindsToInterfaces=(eth0 eth1 tap0) 5 | ## Use the MAC address of eth1 (may also be set to a literal MAC address) 6 | #MACAddress=eth1 7 | IP=dhcp 8 | ## Ignore (R)STP and immediately activate the bridge 9 | #SkipForwardingDelay=yes 10 | -------------------------------------------------------------------------------- /docs/examples/ethernet-custom: -------------------------------------------------------------------------------- 1 | Description='A more versatile static ethernet connection' 2 | Interface=eth0 3 | Connection=ethernet 4 | IP=static 5 | # Any valid iproute command can be placed in this array 6 | IPCustom=('addr add dev eth0 192.168.1.23/24 brd +' 'route add default via 192.168.1.1') 7 | DNS=('192.168.1.1') 8 | # Set a priority for automatic profile selection 9 | #Priority=10 10 | #ExcludeAuto=no 11 | -------------------------------------------------------------------------------- /docs/examples/ethernet-dhcp: -------------------------------------------------------------------------------- 1 | Description='A basic dhcp ethernet connection' 2 | Interface=eth0 3 | Connection=ethernet 4 | IP=dhcp 5 | #DHCPClient=dhcpcd 6 | #DHCPReleaseOnStop=no 7 | ## for DHCPv6 8 | #IP6=dhcp 9 | #DHCP6Client=dhclient 10 | ## for IPv6 autoconfiguration 11 | #IP6=stateless 12 | -------------------------------------------------------------------------------- /docs/examples/ethernet-static: -------------------------------------------------------------------------------- 1 | Description='A basic static ethernet connection' 2 | Interface=eth0 3 | Connection=ethernet 4 | IP=static 5 | Address=('192.168.1.23/24' '192.168.1.87/24') 6 | #Routes=('192.168.0.0/24 via 192.168.1.2') 7 | Gateway='192.168.1.1' 8 | DNS=('192.168.1.1') 9 | 10 | ## For IPv6 autoconfiguration 11 | #IP6=stateless 12 | 13 | ## For IPv6 static address configuration 14 | #IP6=static 15 | #Address6=('1234:5678:9abc:def::1/64' '1234:3456::123/96') 16 | #Routes6=('abcd::1234') 17 | #Gateway6='1234:0:123::abcd' 18 | -------------------------------------------------------------------------------- /docs/examples/macvlan-dhcp: -------------------------------------------------------------------------------- 1 | Description='Virtual LAN with a static MAC on interface eth0 using DHCP' 2 | Interface=mac0 3 | Connection=macvlan 4 | # The variable name is plural, but needs precisely one interface 5 | BindsToInterfaces=eth0 6 | # MACVLAN Mode 7 | Mode="bridge" 8 | # Optional static MAC Address for MACVLAN interface 9 | MACAddress="12:34:56:78:9a:bc" 10 | IP=dhcp 11 | -------------------------------------------------------------------------------- /docs/examples/macvlan-static: -------------------------------------------------------------------------------- 1 | Description='Virtual LAN with random MAC address on interface eth0' 2 | Interface=mac0 3 | Connection=macvlan 4 | # The variable name is plural, but needs precisely one interface 5 | BindsToInterfaces=eth0 6 | # MACVLAN Mode 7 | Mode="bridge" 8 | # Optional static MAC Address for MACVLAN interface 9 | #MACAddress="12:34:56:78:9a:bc" 10 | IP=static 11 | Address="192.168.0.100/24" 12 | Gateway="192.168.0.1" 13 | DNS=("192.168.0.2") 14 | Hostname="myhost" 15 | DNSDomain="mydomain.com" 16 | DNSSearch="mydomain.com" 17 | -------------------------------------------------------------------------------- /docs/examples/mobile_ppp: -------------------------------------------------------------------------------- 1 | Description='Example PPP mobile connection' 2 | Interface=ttyUSB0 3 | Connection=mobile_ppp 4 | 5 | # Use default route provided by the peer (default: true) 6 | #DefaultRoute=true 7 | # Use DNS provided by the peer (default: true) 8 | #UsePeerDNS=true 9 | 10 | # The user and password are not always required 11 | #User='example@yourprovider.com' 12 | #Password='very secret' 13 | 14 | # The access point name you are connecting to 15 | AccessPointName=apn 16 | 17 | # If your device has a PIN code, set it here. Defaults to 'None' 18 | #Pin=None 19 | 20 | # Mode can be one of 3Gpref, 3Gonly, GPRSpref, GPRSonly, None, or SYSCFG=... 21 | # If Mode is set to SYSCFG=..., a custom AT^SYSCFG=... line is sent 22 | # This setting is for Huawei USB modems; all other devices should use None 23 | Mode=3Gpref 24 | -------------------------------------------------------------------------------- /docs/examples/openvswitch: -------------------------------------------------------------------------------- 1 | Description="Example Open vSwitch connection" 2 | Interface=ovs-br0 3 | Connection=openvswitch 4 | BindsToInterfaces=(eth0 eth1) 5 | IP=dhcp 6 | -------------------------------------------------------------------------------- /docs/examples/pppoe: -------------------------------------------------------------------------------- 1 | Description='Example PPPoE connection' 2 | Interface=eth0 3 | Connection=pppoe 4 | User='example@yourprovider.com' 5 | Password='very secret' 6 | 7 | # Always keep a connection established 8 | ConnectionMode='persist' 9 | # Establish connection on demand 10 | #ConnectionMode='demand' 11 | #IdleTimeout=300 12 | 13 | # Use default route provided by the peer (default: true) 14 | #DefaultRoute=true 15 | # Use DNS provided by the peer (default: true) 16 | #UsePeerDNS=true 17 | 18 | # Override default LCP parameters from /etc/ppp/options 19 | #LCPEchoInterval=15 20 | #LCPEchoFailure=10 21 | 22 | # PPPoE options - experts only 23 | # 24 | # PPPoE service name 25 | #PPPoEService='' 26 | # PPPoE access concentrator name 27 | #PPPoEAC='' 28 | # Attach to existing session (sessid:macaddr) 29 | #PPPoESession='' 30 | # Only connect to specified MAC address 31 | #PPPoEMAC='' 32 | # Enable IPv6 support 33 | #PPPoEIP6=yes 34 | -------------------------------------------------------------------------------- /docs/examples/tunnel: -------------------------------------------------------------------------------- 1 | Description='Example tunnel connection' 2 | Interface=tun-ipv6 3 | Connection=tunnel 4 | Mode=sit 5 | Remote='216.66.80.26' 6 | #Local='172.16.0.1' 7 | 8 | ## Optional key in case of Mode=gre 9 | #Key=1234 10 | 11 | IP6=static 12 | Address6='2001:470:1f08:d87::2/64' 13 | Routes6=('::/0') 14 | -------------------------------------------------------------------------------- /docs/examples/tuntap: -------------------------------------------------------------------------------- 1 | Description='Example tuntap connection' 2 | Interface=tun0 3 | Connection=tuntap 4 | Mode='tun' 5 | User='nobody' 6 | Group='nobody' 7 | 8 | ## Example IP configuration 9 | #IP=static 10 | #Address='10.10.1.2/16' 11 | -------------------------------------------------------------------------------- /docs/examples/vlan-dhcp: -------------------------------------------------------------------------------- 1 | Description='Virtual LAN 55 on interface eth0 using DHCP' 2 | Interface=eth0.55 3 | Connection=vlan 4 | # The variable name is plural, but needs precisely one interface 5 | BindsToInterfaces=eth0 6 | VLANID=55 7 | IP=dhcp 8 | -------------------------------------------------------------------------------- /docs/examples/vlan-static: -------------------------------------------------------------------------------- 1 | Description='Virtual LAN 11 on interface eth0' 2 | Interface=eth0.11 3 | Connection=vlan 4 | # The variable name is plural, but needs precisely one interface 5 | BindsToInterfaces=eth0 6 | VLANID=11 7 | IP=static 8 | Address="192.168.0.100/24" 9 | Gateway="192.168.0.1" 10 | DNS=("192.168.0.2") 11 | Hostname="myhost" 12 | DNSDomain="mydomain.com" 13 | DNSSearch="mydomain.com" 14 | -------------------------------------------------------------------------------- /docs/examples/wireguard: -------------------------------------------------------------------------------- 1 | Description="Example WireGuard tunnel connection" 2 | Interface=wg0 3 | Connection=wireguard 4 | WGConfigFile=/etc/wireguard/wg0.conf 5 | 6 | ## Example IP configuration 7 | IP=static 8 | Address=('10.0.0.2/24') 9 | 10 | IP6=static 11 | Address6=('fd00::2/120') 12 | -------------------------------------------------------------------------------- /docs/examples/wireless-open: -------------------------------------------------------------------------------- 1 | Description='A simple open wireless connection' 2 | Interface=wlan0 3 | Connection=wireless 4 | Security=none 5 | ESSID='MyNetwork' 6 | IP=dhcp 7 | # Uncomment this if your ssid is hidden 8 | #Hidden=yes 9 | -------------------------------------------------------------------------------- /docs/examples/wireless-wep: -------------------------------------------------------------------------------- 1 | Description='A simple WEP encrypted wireless connection' 2 | Interface=wlan0 3 | Connection=wireless 4 | 5 | Security=wep 6 | IP=dhcp 7 | 8 | ESSID='MyNetwork' 9 | # Prepend \" to hexadecimal keys, but not to string keys 10 | Key=\"1234567890abcdef 11 | #Key='WirelessKey' 12 | # Uncomment this if your ssid is hidden 13 | #Hidden=yes 14 | # Uncomment this if you are using an ad-hoc connection 15 | #AdHoc=yes 16 | # Set a priority for automatic profile selection 17 | #Priority=10 18 | -------------------------------------------------------------------------------- /docs/examples/wireless-wpa: -------------------------------------------------------------------------------- 1 | Description='A simple WPA encrypted wireless connection' 2 | Interface=wlan0 3 | Connection=wireless 4 | 5 | Security=wpa 6 | IP=dhcp 7 | 8 | ESSID='MyNetwork' 9 | # Prepend hexadecimal keys with \" 10 | # If your key starts with ", write it as '"""' 11 | # See also: the section on special quoting rules in netctl.profile(5) 12 | Key='WirelessKey' 13 | # Uncomment this if your ssid is hidden 14 | #Hidden=yes 15 | # Set a priority for automatic profile selection 16 | #Priority=10 17 | -------------------------------------------------------------------------------- /docs/examples/wireless-wpa-config: -------------------------------------------------------------------------------- 1 | Description='A wpa_supplicant configuration file based wireless connection' 2 | Interface=wlan0 3 | Connection=wireless 4 | Security=wpa-config 5 | WPAConfigFile='/etc/wpa_supplicant.conf' 6 | IP=dhcp 7 | -------------------------------------------------------------------------------- /docs/examples/wireless-wpa-configsection: -------------------------------------------------------------------------------- 1 | Description='A wireless connection using a custom network block configuration' 2 | Interface=wlan0 3 | Connection=wireless 4 | Security=wpa-configsection 5 | IP=dhcp 6 | WPAConfigSection=( 7 | 'ssid="University"' 8 | 'key_mgmt=WPA-EAP' 9 | 'eap=TTLS' 10 | 'group=TKIP' 11 | 'pairwise=TKIP CCMP' 12 | 'anonymous_identity="anonymous"' 13 | 'identity="myusername"' 14 | 'password="mypassword"' 15 | 'priority=1' 16 | 'phase2="auth=PAP"' 17 | ) 18 | -------------------------------------------------------------------------------- /docs/examples/wireless-wpa-static: -------------------------------------------------------------------------------- 1 | Description='A simple WPA encrypted wireless connection using a static IP' 2 | Interface=wlan0 3 | Connection=wireless 4 | Security=wpa 5 | ESSID='MyNetwork' 6 | Key='WirelessKey' 7 | IP=static 8 | Address='192.168.1.23/24' 9 | Gateway='192.168.1.1' 10 | DNS=('192.168.1.1') 11 | # Uncomment this if your ssid is hidden 12 | #Hidden=yes 13 | -------------------------------------------------------------------------------- /docs/netctl-auto.1.txt: -------------------------------------------------------------------------------- 1 | NETCTL-AUTO(1) 2 | ============== 3 | 4 | NAME 5 | ---- 6 | netctl-auto - Control automatic selection of wireless netctl profiles 7 | 8 | 9 | SYNOPSIS 10 | -------- 11 | *netctl-auto* {*COMMAND*} ... 12 | 13 | *netctl-auto* [--help | --version] 14 | 15 | 16 | DESCRIPTION 17 | ----------- 18 | *netctl-auto* may be used to control the automatic network profile 19 | selection offered by the 'netctl-auto@.service' file. See 20 | *netctl.special*(7) for details about the service file. 21 | 22 | 23 | OPTIONS 24 | ------- 25 | The following commands are understood: 26 | 27 | *list*:: 28 | List all profiles which are currently available for automatic 29 | selection. Active profiles will be marked with a `*', disabled 30 | profiles will be marked with a `!'. 31 | 32 | *switch-to [+PROFILE+]*:: 33 | Switch to the network profile specified on the command line. The 34 | specified profile will be enabled if necessary, the state of all 35 | other profiles is not changed. This command does not force 36 | *netctl-auto* to use the specified profile. If a disconnect occurs, 37 | *netctl-auto* may select an alternative profile. 38 | 39 | *is-active [+PROFILE+]*:: 40 | Check whether the network profile specified on the command line is 41 | active. Prints the current state. 42 | 43 | *enable [+PROFILE+]*:: 44 | Enable a previously disabled network profile for automatic 45 | selection. Every time the *netctl-auto* service is started, all 46 | available profiles are enabled by default. 47 | 48 | *disable [+PROFILE+]*:: 49 | Disable the specified profile for automatic selection. This will 50 | only take effect until the *netctl-auto* service is stopped. To 51 | permanently exclude a profile from automatic selection, use the 52 | 'ExcludeAuto=yes' option in the profile. 53 | 54 | *enable-all*:: 55 | Enable all profiles for automatic selection. 56 | 57 | *disable-all*:: 58 | Disable all profiles for automatic selection. 59 | 60 | *is-enabled [+PROFILE+]*:: 61 | Check whether the specified profile is enabled for the *netctl-auto* 62 | service that is currently running. Prints the current enable status. 63 | 64 | *start [+INTERFACE+]*:: 65 | Start automatic profile selection on the specified interface. + 66 | This command should not be invoked directly, use the following 67 | command instead: 68 | ----------------------------------------------- 69 | systemctl start netctl-auto@ 70 | ----------------------------------------------- 71 | 72 | *stop [+INTERFACE+]*:: 73 | Stop automatic profile selection on the specified interface. This 74 | will disconnect the currently active profile on the interface. + 75 | This command should not be invoked directly, use the following 76 | command instead: 77 | ---------------------------------------------- 78 | systemctl stop netctl-auto@ 79 | ---------------------------------------------- 80 | 81 | 82 | EXIT STATUS 83 | ----------- 84 | On success 0 is returned, a non-zero failure code otherwise. 85 | 86 | 87 | ENVIRONMENT 88 | ----------- 89 | '$NETCTL_DEBUG':: 90 | If set to +"yes"+, debugging output is generated. 91 | 92 | 93 | SEE ALSO 94 | -------- 95 | *netctl*(1), *netctl.profile*(5), *netctl.special*(7) 96 | -------------------------------------------------------------------------------- /docs/netctl.1.txt: -------------------------------------------------------------------------------- 1 | NETCTL(1) 2 | ========= 3 | 4 | NAME 5 | ---- 6 | netctl - Control the netctl network profile manager 7 | 8 | 9 | SYNOPSIS 10 | -------- 11 | *netctl* {*COMMAND*} [+PROFILE+] 12 | 13 | *netctl* [--help | --version] 14 | 15 | 16 | DESCRIPTION 17 | ----------- 18 | *netctl* may be used to introspect and control the state of the systemd 19 | services for the network profile manager. 20 | 21 | 22 | OPTIONS 23 | ------- 24 | The following commands are understood: 25 | 26 | *list*:: 27 | List all available profiles. Online profiles will be marked with a 28 | `*', otherwise active profiles will be marked with a `+'. 29 | 30 | *store*:: 31 | Saves which profiles are currently active. 32 | 33 | *restore*:: 34 | Loads the profiles that were active during the last invocation of 35 | `*store*'. 36 | 37 | *stop-all*:: 38 | Stops all active network profiles. 39 | 40 | *start [+PROFILE+]*:: 41 | Start the network profile specified on the command line. 42 | 43 | *stop [+PROFILE+]*:: 44 | Stop the network profile specified on the command line. 45 | 46 | *restart [+PROFILE+]*:: 47 | Restart the network profile specified on the command line. If it is 48 | not started yet, it will be started. 49 | 50 | *switch-to [+PROFILE+]*:: 51 | Starts the network profile specified on the command line after 52 | stopping all profiles that refer to the same interface. 53 | 54 | *is-active [+PROFILE+]*:: 55 | Check whether the network profile specified on the command line is 56 | active. Prints the current state. 57 | 58 | *status [+PROFILE+]*:: 59 | Show terse runtime status information about a profile, followed by 60 | its most recent log data from the journal. 61 | 62 | *enable [+PROFILE+]*:: 63 | Enable the systemd unit for the profile specified. This will create 64 | a unit configuration file. If the file already exists, the command 65 | fails. No other profiles than the one specified will be enabled. 66 | Changes to the general options in a profile specification will not 67 | propagate to the unit configuration file automatically. After such 68 | changes, it is necessary to `*reenable*' the profile. 69 | 70 | *disable [+PROFILE+]*:: 71 | Disable the systemd unit for the profile specified. This will remove 72 | the file created by `*enable*' even if it was customized, so be 73 | careful. 74 | 75 | *reenable [+PROFILE+]*:: 76 | Reenable the systemd unit for the profile specified. This is 77 | effectively a combination of `*disable*' and `*enable*'. 78 | 79 | *is-enabled [+PROFILE+]*:: 80 | Check whether the systemd unit for the specified profile is enabled. 81 | Prints the current enable status. 82 | 83 | *edit [+PROFILE+]*:: 84 | Open the file of the specified profile in an editor. This does not 85 | reenable, restart, or verify any profiles. 86 | 87 | *verify [+PROFILE+]*:: 88 | Check the file of the specified profile for syntax errors. If no 89 | errors are found, no output is produced. 90 | 91 | *wait-online [+PROFILE+]*:: 92 | Wait until the interface of the profile has a routable IP address of 93 | some kind. 94 | 95 | 96 | EXIT STATUS 97 | ----------- 98 | On success 0 is returned, a non-zero failure code otherwise. 99 | 100 | 101 | ENVIRONMENT 102 | ----------- 103 | '$NETCTL_DEBUG':: 104 | If set to +"yes"+, debugging output is generated. + 105 | The value of this variable is independent of the value of the 106 | variable with the same name in profiles. 107 | '$NETCTL_STATE_FILE':: 108 | The location of the state file. Defaults to 109 | '/var/lib/netctl/netctl.state'. 110 | 111 | 112 | SEE ALSO 113 | -------- 114 | *netctl-auto*(1), *netctl.profile*(5), *netctl.special*(7), *systemctl*(1) 115 | -------------------------------------------------------------------------------- /docs/netctl.profile.5.txt: -------------------------------------------------------------------------------- 1 | NETCTL.PROFILE(5) 2 | ================= 3 | 4 | NAME 5 | ---- 6 | netctl.profile - Profile options 7 | 8 | 9 | SYNOPSIS 10 | -------- 11 | netctl.profile 12 | 13 | 14 | DESCRIPTION 15 | ----------- 16 | Profiles for netctl live under '/etc/netctl/' and are plain text files. 17 | The files consist of variable definitions following the bash shell 18 | syntax and are not expected to execute any code. It is good to omit as 19 | much quoting as possible. For a few WPA-related variables, special 20 | quoting rules (see below) apply. 21 | 22 | The name of the profile is the name of the file. Profile names must not 23 | contain newlines and should not end in '.action', '.conf', or 24 | '.service'. Whenever a profile is read, all executable scripts in 25 | '/etc/netctl/hooks/' and any executable script in 26 | '/etc/netctl/interfaces/' with the name of the interface for the profile 27 | are sourced. The name of the current profile is available via the 28 | 'Profile' variable in the environment of the sourced scripts. On 29 | starting or stopping a profile, the respective command is available via 30 | the 'Command' variable. Declarations in an interface script override 31 | declarations in a profile, which override declarations in hooks. For 32 | each connection type, there are example profile files in 33 | '/etc/netctl/examples/'. 34 | 35 | 36 | AVAILABLE CONNECTION TYPES 37 | -------------------------- 38 | +ethernet+:: 39 | For wired connections. 40 | +wireless+:: 41 | For wireless connections. This connection type requires 42 | *wpa_supplicant* to be available. 43 | +bond+:: 44 | For bonded interfaces. 45 | +bridge+:: 46 | For bridge interfaces. 47 | +dummy+:: 48 | For dummy interfaces. 49 | +ppp+:: 50 | For PPP connections (currently only PPPoE). 51 | +pppoe+:: 52 | For PPPoE connections. 53 | +mobile_ppp+:: 54 | For mobile broadband PPP connections that use a USB modem. 55 | +openvswitch+:: 56 | For Open vSwitch bridge interfaces. 57 | +tunnel+:: 58 | For tunnel interfaces. 59 | +tuntap+:: 60 | For TUN/TAP interfaces. 61 | +vlan+:: 62 | For VLANs on ethernet-like connections. 63 | +macvlan+:: 64 | For MACVLANs on ethernet-like connections. 65 | +wireguard+:: 66 | For WireGuard interfaces. 67 | 68 | 69 | GENERAL OPTIONS 70 | --------------- 71 | 'Description=':: 72 | A description of the profile. 73 | 74 | 'Connection=' [mandatory for all profiles]:: 75 | The connection type used by the profile. 76 | 77 | 'Interface=' [mandatory for all profiles]:: 78 | The name of the associated network interface. The interface name 79 | should not be quoted. 80 | 81 | 'BindsToInterfaces=()':: 82 | An array of physical network interfaces that this profile needs 83 | before it can be started. For `enabled' profiles, *systemd* will 84 | wait for the presence of the specified interfaces before starting a 85 | profile. If this variable is not specified, it defaults to the value 86 | of 'Interface='. 87 | 88 | 'MACAddress=':: 89 | Optional MAC address for newly created interfaces. When set to the 90 | name of an existing interface, the address of that interface is used. 91 | The connection types that create an interface and are able to set a 92 | MAC address are +bond+, +bridge+, +dummy+, +vlan+, and +macvlan+. 93 | 94 | 'After=()':: 95 | An array of profile names that should be started before this profile 96 | is started. This is only an ordering dependency and is not intended 97 | to be a list of profiles that this profile requires. The meaning is 98 | the same as 'After=' in *systemd.unit*(5). 99 | 100 | 'WaitOnline=':: 101 | Set to `++yes++' to consider the profile activated only when it is 102 | online. Defaults to `++no++'. 103 | 104 | 'ExecUpPost=':: 105 | A command that is executed after a connection is established. If the 106 | specified command returns anything other than 0 (success), *netctl* 107 | will abort and stop the profile. If the command should be allowed to 108 | fail, add ``|| true`' to the end of it. 109 | 110 | 'ExecDownPre=':: 111 | A command that is executed before a connection is brought down. 112 | Similar precautions should be taken as with 'ExecUpPost='. 113 | 114 | 'TimeoutUp':: 115 | Maximum time, in seconds, to wait for an interface to get up. 116 | Defaults to `++5++'. 117 | 118 | 'ForceConnect=':: 119 | Set to `++yes++' to force connecting even if the interface is up. 120 | Do not use this unless you know what you are doing. 121 | 122 | 'ExcludeAuto=':: 123 | Whether or not to exclude this profile from automatic profile 124 | selection. Defaults to `++no++' for wireless and DHCP enabled 125 | connections and to `++yes++' otherwise. 126 | 127 | 'NETCTL_DEBUG=':: 128 | Set to `++yes++' to generate debugging output. 129 | 130 | 131 | IP OPTIONS 132 | ---------- 133 | These options apply to all connections that set up an IP-enabled 134 | network. In particular, these connection types are +ethernet+, 135 | +wireless+, +bond+, +bridge+, +tunnel+, +tuntap+, and +vlan+. 136 | 137 | 'IP=' [mandatory for IPv4]:: 138 | One of `static', `dhcp', or `no', depending on the desired way of 139 | obtaining an address. 140 | 141 | 'IP6=' [mandatory for IPv6]:: 142 | One of `static', `stateless', `dhcp-noaddr', `dhcp', `no' or left 143 | out (empty) altogether. The difference between not specifying and 144 | setting to `no' is in the handling of __router advertisement__ 145 | packages, which is blocked by `no'. 146 | 147 | 'Address=()' [requires 'IP=static']:: 148 | An array of IP addresses suffixed with `++/++'. 149 | Leaving out brackets for arrays consisting of a single element is 150 | accepted in the Bash syntax. 151 | 152 | 'Gateway=' [requires 'IP=static']:: 153 | An IP routing gateway address. 154 | 155 | 'Routes=()':: 156 | An array of custom routes of the form + 157 | `**
** via ****'. 158 | 159 | 'Address6=()' [requires 'IP6=static' or 'IP6=stateless']:: 160 | An array of IPv6 addresses. Prefix length may be specified via 161 | `1234:bcd::11/64' syntax. It is possible to specify modifiers, in 162 | particular, `1234:bcd::11/64 nodad' disables Duplicate Address 163 | Detection for the address. 164 | 165 | 'Gateway6=' [requires 'IP6=static' or 'IP6=stateless']:: 166 | An IPv6 routing gateway address. 167 | 168 | 'Routes6=()':: 169 | An array of custom routes of the form + 170 | `**
** via ****'. 171 | 172 | 'DHCPClient=' [requires 'IP=dhcp']:: 173 | The name of the DHCP client to use. By default, *netctl* comes with 174 | support for `dhcpcd' and `dhclient'. Clients may accept additional 175 | options through client-specific variables. Command line options for 176 | *dhcpcd*(8) are read from 'DhcpcdOptions=' (defaults to 177 | `++-L++{empty}'). Command line options for *dhclient*(8) are read 178 | from 'DhclientOptions='. Defaults to `++dhcpcd++'. 179 | 180 | 'DHCP6Client=' [requires 'IP6=dhcp' or 'IP6=dhcp-noaddr']:: 181 | The name of the DHCPv6 client to use. By default, `dhcpcd' and 182 | `dhclient' are supported. Command line options for the IPv6 183 | instance of *dhcpcd*(8) are read from 'DhcpcdOptions6='. Command 184 | line options for the IPv6 instance of *dhclient*(8) are read from 185 | 'DhclientOptions6='. Defaults to `++dhclient++'. 186 | 187 | 'DHCPReleaseOnStop=':: 188 | Set to `++yes++' to release the DHCP lease when the profile is 189 | stopped. 190 | 191 | 'IPCustom=()':: 192 | An array of argument lines to pass to `ip`. This can be used to 193 | achieve complicated configurations within the framework of *netctl*. 194 | 195 | 'Hostname=':: 196 | A transient hostname for the system. 197 | 198 | 'DNS=()':: 199 | An array of DNS nameservers. Simply specify the IP addresses of each 200 | of the DNS nameservers. 201 | 202 | 'DNSDomain=':: 203 | A `++domain++' line for '/etc/resolv.conf', passed to 204 | *resolvconf*(5). 205 | 206 | 'DNSSearch=':: 207 | A `++search++' line for '/etc/resolv.conf', passed to 208 | *resolvconf*(5). 209 | 210 | 'DNSOptions=()':: 211 | An array of `++options++' lines for '/etc/resolv.conf', passed to 212 | *resolvconf*(5). 213 | 214 | 'TimeoutDHCP=':: 215 | Maximum time, in seconds, to wait for DHCP to be successful. 216 | Defaults to `++30++'. 217 | 218 | 'TimeoutDAD=':: 219 | Maximum time, in seconds, to wait for IPv6's Duplicate Address 220 | Detection to succeed. Defaults to `++3++'. 221 | 222 | 'SkipDAD=':: 223 | Whether or not to bypass Duplicate Address Detection altogether. 224 | Defaults to `++no++'. 225 | 226 | 227 | OPTIONS FOR `ethernet' CONNECTIONS 228 | ---------------------------------- 229 | Next to the *ip options*, the following are understood for connections 230 | of the `ethernet' type: 231 | 232 | 'Auth8021X=':: 233 | Set to `++yes++' to use 802.1x authentication. 234 | 235 | 'WPAConfigFile=':: 236 | Path to a *wpa_supplicant* configuration file. Defaults to 237 | '/etc/wpa_supplicant.conf'. 238 | 239 | 'WPADriver=':: 240 | The *wpa_supplicant* driver to use for 802.1x authentication. 241 | Defaults to `++wired++'. 242 | 243 | 'TimeoutCarrier=':: 244 | Maximum time, in seconds, to wait for a carrier. Defaults to 245 | `++5++'. 246 | 247 | 'TimeoutWPA=':: 248 | Maximum time, in seconds, to wait for 802.1x authentication to 249 | succeed. Defaults to `++15++'. 250 | 251 | 'SkipNoCarrier=':: 252 | Whether or not the absence of a carrier (plugged-in cable) is 253 | acceptable. Defaults to `++no++'. 254 | 255 | 'Priority=':: 256 | Priority level of the profile. In case of automatic profile 257 | selection, profiles are tried in decreasing order of priority. 258 | Defaults to `++1++' in DHCP enabled profiles and to `++0++' 259 | otherwise. 260 | 261 | 262 | OPTIONS FOR `wireless' CONNECTIONS 263 | ---------------------------------- 264 | Next to the *ip options*, the following are understood for connections 265 | of the `wireless' type: 266 | 267 | 'Security=':: 268 | One of `none', `wep', `wpa', `wpa-configsection', or `wpa-config'. 269 | Defaults to `++none++'. 270 | 271 | 'ESSID=' [mandatory]:: 272 | The name of the network to connect to. 273 | Special quoting rules (see below) apply. 274 | 275 | 'AP=':: 276 | The BSSID (MAC address) of the access point to connect to. 277 | 278 | 'Key=':: 279 | The secret key to a WEP, or WPA encrypted network. 280 | Special quoting rules (see below) apply. 281 | 282 | 'Hidden=':: 283 | Whether or not the specified network is a hidden network. Defaults 284 | to `++no++'. 285 | 286 | 'AdHoc=':: 287 | Whether or not to use ad-hoc mode. Defaults to `++no++'. 288 | 289 | 'ScanFrequencies=':: 290 | A space-separated list of frequencies in MHz to scan when searching 291 | for the network. Defaults to all available frequencies. 292 | 293 | 'Frequency=':: 294 | A frequency in MHz to use in ad-hoc mode when a new IBSS is created 295 | (i.e. the network is not already present). 296 | 297 | 'Priority=':: 298 | Priority group for the network. In case of automatic profile 299 | selection, the matched network with the highest priority will be 300 | selected. Defaults to `++0++'. 301 | 302 | 'WPAConfigSection=()' [mandatory for 'Security=wpa-configsection']:: 303 | Array of lines that form a network block for *wpa_supplicant*. All 304 | of the above options will be ignored. 305 | 306 | 'WPAConfigFile=':: 307 | Path to a *wpa_supplicant* configuration file. Used only for 308 | 'Security=wpa-config'. All options except 'WPADriver=', 309 | 'TimeoutWPA=', and 'RFKill=' will be ignored. The profile is 310 | excluded from automatic profile selection. Defaults to 311 | '/etc/wpa_supplicant.conf'. 312 | 313 | 'Country=':: 314 | The country for which frequency regulations will be enforced. 315 | 316 | 'WPAGroup=':: 317 | Group that has the authority to configure *wpa_supplicant* via its 318 | control interface. Defaults to `++wheel++'. 319 | 320 | 'WPADriver=':: 321 | The *wpa_supplicant* driver to use. Defaults to `++nl80211,wext++'. 322 | 323 | 'TimeoutWPA=':: 324 | Maximum time, in seconds, to wait for steps in the association and 325 | authentication to succeed. Defaults to `++15++'. 326 | 327 | 'RFKill=':: 328 | The name of an *rfkill* device. When specified, the device is used 329 | to block/unblock the interface when appropriate. Names can be found 330 | in '/sys/class/rfkill/rfkillX/name'. It is also possible to set this 331 | variable to `++auto++'. In that case an *rfkill* device that is 332 | associated with the network interface is used. 333 | 334 | 335 | OPTIONS FOR `bond' CONNECTIONS 336 | ------------------------------ 337 | The interfaces of 'BindsToInterfaces=' are bound together in the 338 | interface named by 'Interface='. Next to the *ip options*, the 339 | following is understood for connections of the `bond' type: 340 | 341 | 'Mode=':: 342 | The bonding policy. See the kernel documentation on bonding for 343 | details. 344 | 345 | 'LinkOptions=':: 346 | Additional options to be passed to *ip link*. Run 347 | *ip link add type bond help* to see the available options. 348 | 349 | 350 | OPTIONS FOR `bridge' CONNECTIONS 351 | -------------------------------- 352 | The interfaces of 'BindsToInterfaces=' take part in the bridge named by 353 | 'Interface='. Next to the *ip options*, the following is understood for 354 | connections of the `bridge' type: 355 | 356 | 'SkipForwardingDelay=':: 357 | Skip \(R)STP and immediately activate all bridge members. This can 358 | be useful when DHCP is used on the bridge. 359 | 360 | 'LinkOptions=':: 361 | Additional options to be passed to *ip link*. Run 362 | *ip link add type bridge help* to see the available options. 363 | 364 | 365 | OPTIONS FOR `dummy' CONNECTIONS 366 | ------------------------------- 367 | The name of the dummy interface is specified in 'Interface='. Only the 368 | *ip options* are understood for connections of the `dummy' type. 369 | 370 | 371 | OPTIONS FOR `ppp' CONNECTIONS 372 | ----------------------------- 373 | This connection type is identical to the `pppoe' type below, with the 374 | ethernet interface specified in 'BindsToInterfaces='. The value of 375 | 'Interface=' must be of the form `ppp<++n++>', where ++n++ is passed on 376 | to 'PPPUnit='. 377 | 378 | 379 | OPTIONS FOR `pppoe' CONNECTIONS 380 | ------------------------------- 381 | The interface to dial peer-to-peer over ethernet is specified in 382 | 'Interface='. The following options are understood for connections of 383 | the `pppoe' type: 384 | 385 | 'User=' and 'Password=':: 386 | The username and password to connect with. 387 | 388 | 'ConnectionMode=':: 389 | One of `persist' or `demand', depending on how a connection should 390 | be established. Defaults to `++persist++'. 391 | 392 | 'IdleTimeout=' [requires 'ConnectionMode=demand']:: 393 | The idle time (in seconds) after which the PPP daemon should 394 | disconnect. 395 | 396 | 'MaxFail=':: 397 | The number of consecutive failed connection attempts to tolerate. 398 | A value of 0 means no limit. Defaults to `++5++'. 399 | 400 | 'DefaultRoute=':: 401 | Whether or not to use the default route provided by the peer. 402 | Defaults to `++yes++'. 403 | 404 | 'UsePeerDNS=':: 405 | Whether or not to use the DNS servers provided by the peer. 406 | Defaults to `++yes++'. 407 | 408 | 'PPPUnit=':: 409 | The PPP unit number in the interface name (`ppp0', `ppp1', etc.). 410 | 411 | 'LCPEchoInterval=' and 'LCPEchoFailure=':: 412 | These options override default LCP parameters from 413 | `/etc/ppp/options'. 414 | 415 | 'OptionsFile=':: 416 | A file to read additional *pppd*(8) options from. 417 | 418 | The following advanced options are also understood: 419 | 420 | 'PPPoEService=':: 421 | The PPPoE service name. 422 | 423 | 'PPPoEAC=':: 424 | The PPPoE access concentrator name. 425 | 426 | 'PPPoESession=':: 427 | An existing session to attach to. This option is of the form 428 | `sessid:macaddr'. 429 | 430 | 'PPPoEMAC=':: 431 | A MAC address to restrict the connection to. 432 | 433 | 'PPPoEIP6=':: 434 | Whether or not to enable IPv6CP and IPv6 protocols. When set to 435 | `no', IPv6CP negotiation and IPv6 communication is explicitly 436 | disabled. 437 | 438 | 439 | OPTIONS FOR `mobile_ppp' CONNECTIONS 440 | ------------------------------------ 441 | The name of the USB serial device is specified in 'Interface='. The 442 | following options are understood for connections of the `mobile_ppp' 443 | type: 444 | 445 | 'User=' and 'Password=':: 446 | The username and password to connect with. These are unset by 447 | default, as they are often not required. 448 | 449 | 'AccessPointName=':: 450 | The access point name (APN) to present to the carrier. This is 451 | specific to your ISP. 452 | 453 | 'Pin=':: 454 | If your modem requires a PIN to unlock, set it here. 455 | 456 | 'PhoneNumber':: 457 | The number to dial. Defaults to `++*99#++'. 458 | 459 | 'Mode=':: 460 | The connection mode. Can be one of `3Gpref', `3Gonly', `GPRSpref', 461 | `GPRSonly', `None', or a custom +AT^SYSCFG=...+ line specified as 462 | `++SYSCFG=...++{empty}'. This generates +AT+ commands specific to 463 | certain Huawei modems; all other devices should leave this option 464 | unset or set to `None'. 465 | 466 | 'Init=':: 467 | An initialization string sent to the modem before dialing. This 468 | string is sent after sending ``ATZ''. Defaults to 469 | `++ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0++'. 470 | 471 | 'ChatScript=':: 472 | Path to a chat file. If specified, no chat script will be generated 473 | and all of the above options except 'User=' and 'Password=' will be 474 | ignored. 475 | 476 | 'MaxFail=':: 477 | The number of consecutive failed connection attempts to tolerate. 478 | A value of 0 means no limit. Defaults to `++5++'. 479 | 480 | 'DefaultRoute=':: 481 | Whether or not to use the default route provided by the peer. 482 | Defaults to `++yes++'. 483 | 484 | 'UsePeerDNS=':: 485 | Whether or not to use the DNS servers provided by the peer. 486 | Defaults to `++yes++'. 487 | 488 | 'PPPUnit=':: 489 | The PPP unit number in the interface name (`ppp0', `ppp1', etc.). 490 | 491 | 'OptionsFile=':: 492 | A file to read additional *pppd*(8) options from. 493 | 494 | 'RFKill=':: 495 | The name of an *rfkill* device. When specified, the device is used 496 | to block/unblock the interface when appropriate. Names can be found 497 | in '/sys/class/rfkill/rfkillX/name'. 498 | 499 | 500 | OPTIONS FOR `openvswitch' CONNECTIONS 501 | ------------------------------------- 502 | The interfaces of 'BindsToInterfaces=' take part in the bridge named by 503 | 'Interface='. Only the *ip options* are understood for connections of 504 | the `openvswitch' type. 505 | 506 | 507 | OPTIONS FOR `tunnel' CONNECTIONS 508 | -------------------------------- 509 | The name of the tunnel interface is specified in 'Interface='. Next to 510 | the *ip options*, the following are understood for connections of the 511 | `tunnel' type: 512 | 513 | 'Mode=':: 514 | The tunnel type (e.g. `sit'). See *ip-tunnel*(8) for available 515 | modes. 516 | 517 | 'Local=':: 518 | The address of the local end of the tunnel. 519 | 520 | 'Remote=':: 521 | The address of the remote end of the tunnel. 522 | 523 | 'Key=' [requires 'Mode=gre']:: 524 | A key identifying an individual traffic flow within a tunnel. 525 | 526 | 527 | OPTIONS FOR `tuntap' CONNECTIONS 528 | -------------------------------- 529 | The name of the tuntap interface is specified in 'Interface='. Next to 530 | the *ip options*, the following are understood for connections of the 531 | `tuntap' type: 532 | 533 | 'Mode=':: 534 | Either `tun', or `tap'. 535 | 536 | 'User=':: 537 | The owning user of the tun/tap interface. 538 | 539 | 'Group=':: 540 | The owning group of the tun/tap interface. 541 | 542 | 543 | OPTIONS FOR `vlan' CONNECTIONS 544 | ------------------------------ 545 | The name of the vlan interface is specified in 'Interface='. The 546 | underlying physical interface is specified in 'BindsToInterfaces='. 547 | Hence, for vlan profiles, 'BindsToInterfaces=' contains the name of a 548 | single network interface. 549 | 550 | All options for connections of the `ethernet' type are understood for 551 | connections of the `vlan' type. Additionally, connections of the `vlan' 552 | type must set a vlan identifier using 'VLANID='. See *ip*(8) for 553 | details. 554 | 555 | 556 | OPTIONS FOR `macvlan' CONNECTIONS 557 | --------------------------------- 558 | The name of the macvlan interface is specified in 'Interface='. The 559 | underlying physical interface is specified in 'BindsToInterfaces='. 560 | Hence, for macvlan profiles, 'BindsToInterfaces=' contains the name of 561 | a single network interface. 562 | 563 | All options for connections of the `ethernet' type are understood for 564 | connections of the `macvlan' type. Next to the *ip options*, the 565 | following are understood for connections of the `macvlan' type: 566 | 567 | 'Mode=':: 568 | Either `bridge', `vepa', `private', or `passthru'. See *ip*(8) for 569 | details. 570 | 571 | 572 | OPTIONS FOR `wireguard' CONNECTIONS 573 | ----------------------------------- 574 | The name of the WireGuard interface is specified in 'Interface='. Next 575 | to the *ip options*, the following are understood for connections of 576 | the `wireguard' type: 577 | 578 | 'WGConfigFile=':: 579 | Path to a *WireGuard* configuration file. Defaults to 580 | '/etc/wireguard/$Interface.conf'. 581 | 582 | 583 | SPECIAL QUOTING RULES 584 | --------------------- 585 | Configuration files for *wpa_supplicant* use non-standard quoting. 586 | Therefore, non-standard quoting rules exist for some variables for 587 | connections of the `wireless' type. In particular, these variables are 588 | 'ESSID=', and 'Key='. 589 | 590 | A variable is considered *quoted* by *wpa_supplicant* if it is enclosed 591 | in double quotes ("). A variable is considered *non-quoted* by 592 | *wpa_supplicant* if it does not start with a double quote. Hexadecimal 593 | values are specified *non-quoted* in configuration files of 594 | *wpa_supplicant*. In *netctl*, variables are written to *wpa_supplicant* 595 | configuration files *quoted* by default. When special quoting rules 596 | apply, it is possible to specify an unquoted (hexadecimal) value using a 597 | special syntax. 598 | 599 | The special quoting rules of *netctl* are as follows. A string that 600 | starts with a literal double quote is considered *non-quoted*. Any other 601 | string is considered *quoted*. It is possible to specify quoted strings 602 | that start with a double quote by quoting manually. An extreme example 603 | is the specification of a *quoted* double quote: '`X='""""'`'. On the 604 | other end of the spectrum there is the *non-quoted* backslash: 605 | '`X=\"\\`'. 606 | 607 | Further examples of *quoted* strings (all equivalent): 608 | ------------- 609 | X=string 610 | X="string" 611 | X='""string"' 612 | ------------- 613 | 614 | Further examples of *non-quoted* strings (all equivalent): 615 | ------------ 616 | X=\"string 617 | X="\"string" 618 | X='"string' 619 | ------------ 620 | 621 | A mnemonic is to think of the prefix ``\"`' as saying `non'-`quote'. 622 | 623 | 624 | SEE ALSO 625 | -------- 626 | *netctl*(1), *resolvconf.conf*(5) 627 | -------------------------------------------------------------------------------- /docs/netctl.special.7.txt: -------------------------------------------------------------------------------- 1 | NETCTL.SPECIAL(7) 2 | ================= 3 | 4 | NAME 5 | ---- 6 | netctl.special - Special netctl systemd units 7 | 8 | 9 | SYNOPSIS 10 | -------- 11 | netctl.service, netctl-auto.service, netctl-ifplugd.service, 12 | netctl-wait-online.service 13 | 14 | 15 | DESCRIPTION 16 | ----------- 17 | Bundled with netctl come a few systemd units that are not controlled 18 | through the netctl command. They can be used through the systemctl 19 | utility of systemd. 20 | 21 | 22 | SPECIAL UNITS 23 | ------------- 24 | netctl.service:: 25 | When started, this unit tries to start the profiles that were 26 | running when the unit was last stopped. In some cases, the interface 27 | a profile binds to might not be available yet, when 'netctl.service' 28 | tries to bring a profile up. A simple, hackish, solution is to do: 29 | -------------------------------------------------------------------- 30 | echo "[[ -t 0 ]] || sleep 3" > /etc/netctl/interfaces/ 31 | chmod 755 /etc/netctl/interfaces/ 32 | -------------------------------------------------------------------- 33 | A more concise solution is to first enable a profile through netctl 34 | and then disable it again through systemctl: 35 | -------------------------------------------------------------------- 36 | netctl enable 37 | systemctl disable netctl@ 38 | -------------------------------------------------------------------- 39 | This way the unit configuration file for the profile remains in 40 | existence, while the profile is not enabled. 41 | 42 | netctl-sleep.service:: 43 | When enabled, this unit stores and stops the active network profiles 44 | before the machine is put to sleep. After the system is resumed, 45 | previously stored profiles are restarted. 46 | 47 | netctl-auto@.service:: 48 | This unit issues a scan on the interface it is used for and tries to 49 | start a profile for a network it finds. It is targeted at wireless 50 | interfaces. Profile specific values for 'WPADriver' are ignored, but 51 | it is possible to specify 'WPADriver=' in an interface hook 52 | ('/etc/netctl/interfaces/'). + 53 | Use *netctl-auto*(1) instead of *netctl(1)* to control the automatic 54 | profile selection when using this unit. 55 | 56 | netctl-ifplugd@.service:: 57 | This unit starts ifplugd on the interface it is used for. It will 58 | try to start a netctl profile whenever a cable is plugged into the 59 | interface and stop the profile when the cable is unplugged. Note 60 | that this unit does not provide 'network.target'. 61 | 62 | netctl-wait-online.service:: 63 | When activated, this unit waits for all enabled netctl profiles to 64 | come online. Enabling this unit causes 'network-online.target' to 65 | only be reached once all enabled netctl profiles are fully 66 | connected. The maximum time, in seconds, to wait for profiles can be 67 | passed to this unit via 'TIMEOUT_ONLINE='. The default value is 68 | +120+. If a timeout occurs, the service enters a failed state. 69 | 70 | 71 | SEE ALSO 72 | -------- 73 | *netctl*(1), *netctl-auto*(1), *netctl.profile*(5) 74 | -------------------------------------------------------------------------------- /docs/wifi-menu.1.txt: -------------------------------------------------------------------------------- 1 | WIFI-MENU(1) 2 | ============ 3 | 4 | NAME 5 | ---- 6 | wifi-menu - Interactively connect to a wireless network 7 | 8 | 9 | SYNOPSIS 10 | -------- 11 | *wifi-menu* [-o | --obscure] [+INTERFACE+] 12 | 13 | *wifi-menu* [-h | --help] 14 | 15 | 16 | DESCRIPTION 17 | ----------- 18 | *wifi-menu* allows to interactively connect to a wireless network on 19 | +INTERFACE+ using a netctl profile. In case no netctl profile is 20 | available, one can be generated. If only one wireless interface is 21 | available, +INTERFACE+ can be omitted. 22 | 23 | *wifi-menu* is only able to generate netctl profiles for simple network 24 | configurations. Profiles for more complex configurations must be set up 25 | manually. See *netctl.profile*(5) for more information. 26 | 27 | 28 | OPTIONS 29 | ------- 30 | +-h+, +--help+:: 31 | Print a short help text and exit. 32 | 33 | +-o+, +--obscure+:: 34 | Show asterisks for the characters of the password and store the password 35 | as a hexadecimal pre-shared key. 36 | 37 | +INTERFACE+:: 38 | The wireless network interface to use for connecting. 39 | 40 | 41 | EXIT STATUS 42 | ----------- 43 | +0+:: 44 | The interface connected to the wireless network successfully. 45 | 46 | +1+:: 47 | The connection attempt was canceled. 48 | 49 | +2+:: 50 | The connection attempt failed. 51 | 52 | +3+:: 53 | No wireless networks were found. 54 | 55 | +4+:: 56 | Invalid passphrase length (+WEP+ keys must be between 8 and 63 57 | characters in length). 58 | 59 | +7+:: 60 | An unexpected error code was received. 61 | 62 | +255+:: 63 | The command was invalid or the connection attempt was aborted. 64 | 65 | 66 | NOTES 67 | ----- 68 | Establishing a connection may take a minute. While establishing a 69 | connection, nothing is shown on screen. 70 | 71 | Starting a connection on an interface that is controlled by 72 | *netctl-auto* will cause *wifi-menu* to switch to the selected network. 73 | The interface will continue to be controlled by *netctl-auto*. 74 | 75 | 76 | ENVIRONMENT 77 | ----------- 78 | '$NETCTL_DEBUG':: 79 | If set to +"yes"+, debugging output is generated. 80 | 81 | 82 | FILES 83 | ----- 84 | '/etc/netctl':: 85 | Directory where generated profiles are stored. 86 | 87 | 88 | SEE ALSO 89 | -------- 90 | *netctl*(1), *netctl-auto*(1) 91 | -------------------------------------------------------------------------------- /services/netctl-auto@.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Automatic wireless network connection using netctl profiles 3 | Documentation=man:netctl.special(7) 4 | Requisite=multi-user.target 5 | BindsTo=sys-subsystem-net-devices-%i.device 6 | After=sys-subsystem-net-devices-%i.device network-pre.target 7 | Before=network.target 8 | Wants=network.target 9 | 10 | [Service] 11 | Type=forking 12 | RemainAfterExit=yes 13 | ExecStart=/usr/bin/netctl-auto start %I 14 | ExecStop=/usr/bin/netctl-auto stop %I 15 | ExecStopPost=/usr/bin/netctl-auto clean %I 16 | 17 | [Install] 18 | WantedBy=sys-subsystem-net-devices-%i.device 19 | -------------------------------------------------------------------------------- /services/netctl-ifplugd@.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Automatic wired network connection using netctl profiles 3 | Documentation=man:netctl.special(7) 4 | Requisite=multi-user.target 5 | BindsTo=sys-subsystem-net-devices-%i.device 6 | After=sys-subsystem-net-devices-%i.device network-pre.target 7 | 8 | [Service] 9 | NotifyAccess=all 10 | ExecStart=/usr/bin/ifplugd -i %I -r /etc/ifplugd/netctl.action -d 0 -bfIns 11 | ExecStop=/usr/bin/ifplugd -i %I -k -W 12 | 13 | [Install] 14 | WantedBy=sys-subsystem-net-devices-%i.device 15 | -------------------------------------------------------------------------------- /services/netctl-sleep.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=netctl sleep hook 3 | Documentation=man:netctl.special(7) 4 | Before=sleep.target 5 | StopWhenUnneeded=yes 6 | 7 | [Service] 8 | Type=oneshot 9 | RemainAfterExit=yes 10 | ExecStart=/usr/bin/netctl store ; /usr/bin/netctl stop-all 11 | ExecStop=-/usr/bin/netctl restore 12 | 13 | [Install] 14 | WantedBy=sleep.target 15 | -------------------------------------------------------------------------------- /services/netctl-wait-online.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Wait for the enabled netctl profiles to come online 3 | Documentation=man:netctl.special(7) 4 | After=network.target 5 | Before=network-online.target 6 | 7 | [Service] 8 | Type=oneshot 9 | RemainAfterExit=yes 10 | ExecStart=/usr/lib/netctl/network wait-online 11 | 12 | [Install] 13 | WantedBy=network-online.target 14 | -------------------------------------------------------------------------------- /services/netctl.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=(Re)store the netctl profile state 3 | Documentation=man:netctl.special(7) 4 | Before=network.target 5 | 6 | [Service] 7 | Type=oneshot 8 | RemainAfterExit=yes 9 | ExecStart=-/usr/bin/netctl restore 10 | ExecStop=/usr/bin/netctl store 11 | 12 | [Install] 13 | WantedBy=multi-user.target 14 | -------------------------------------------------------------------------------- /services/netctl@.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Networking for netctl profile %I 3 | Documentation=man:netctl.profile(5) 4 | After=network-pre.target 5 | Before=network.target netctl.service 6 | Wants=network.target 7 | 8 | [Service] 9 | Type=notify 10 | NotifyAccess=exec 11 | RemainAfterExit=yes 12 | ExecStart=/usr/lib/netctl/network start %I 13 | ExecStop=/usr/lib/netctl/network stop %I 14 | -------------------------------------------------------------------------------- /src/ifplugd.action: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # 3 | # ifplugd.action script for netctl 4 | 5 | . /usr/lib/netctl/globals 6 | 7 | PROFILE_FILE="$STATE_DIR/ifplugd-$1.profile" 8 | 9 | case "$2" in 10 | up) 11 | while IFS= read -r profile; do 12 | if ForceConnect=yes "$SUBR_DIR/network" start "$profile"; then 13 | mkdir -p "$(dirname "$PROFILE_FILE")" 14 | printf '%s' "$profile" > "$PROFILE_FILE" 15 | exit 0 16 | fi 17 | done < <(filter_profiles "$1" ethernet | while IFS= read -r profile; do 18 | report_debug "Examining profile '$profile'" 19 | ( 20 | load_profile "$profile" > /dev/null 21 | # Prioritize dhcp based profiles as they can outright fail, whereas 22 | # it is difficult to tell if a profile with a static address fails 23 | if [[ $IP == "dhcp" || $IP6 == dhcp* ]]; then 24 | : ${ExcludeAuto:=no} 25 | : ${Priority:=1} 26 | fi 27 | is_yes "${ExcludeAuto:-yes}" && exit 28 | printf '%i\t%s\n' "${Priority:-0}" "$profile" 29 | report_debug "Included profile '$profile'" 30 | ) 31 | done | sort -nrs -k 1,1 | cut -f 2-) 32 | report_error "Could not start any suitable profile" 33 | ;; 34 | down) 35 | if [[ -e "$PROFILE_FILE" ]]; then 36 | if ForceConnect=yes "$SUBR_DIR/network" stop "$(< "$PROFILE_FILE")"; then 37 | rm -f "$PROFILE_FILE" 38 | exit 0 39 | fi 40 | fi 41 | ;; 42 | *) 43 | echo "Wrong arguments" >&2 44 | ;; 45 | esac 46 | 47 | exit 1 48 | 49 | 50 | # vim: ft=sh ts=4 et sw=4: 51 | -------------------------------------------------------------------------------- /src/lib/auto.action: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | . /usr/lib/netctl/globals 4 | . "$SUBR_DIR/ip" 5 | 6 | export INTERFACE="$1" 7 | export ACTION="$2" 8 | PROFILE_FILE="$STATE_DIR/netctl-auto-$INTERFACE.profile" 9 | 10 | case $ACTION in 11 | CONNECTED) 12 | load_profile "$WPA_ID_STR" 13 | DhcpcdOptions+=" -K -L" 14 | ip_set || exit 1 15 | mkdir -p "$(dirname "$PROFILE_FILE")" 16 | printf '%s' "$Profile" > "$PROFILE_FILE" 17 | # Sandbox the eval 18 | if ! ( do_debug eval "$ExecUpPost" ); then 19 | # Failing ExecUpPost will take the connection down 20 | netctl-auto stop "$INTERFACE" 21 | exit 1 22 | fi 23 | ;; 24 | DISCONNECTED) 25 | if [[ -s "$PROFILE_FILE" ]]; then 26 | load_profile "$(< "$PROFILE_FILE")" 27 | rm -f "$PROFILE_FILE" 28 | # Sandbox the eval 29 | if ! ( do_debug eval "$ExecDownPre" ); then 30 | exit 1 31 | fi 32 | ip_unset 33 | fi 34 | ;; 35 | esac 36 | 37 | 38 | # vim: ft=sh ts=4 et sw=4: 39 | -------------------------------------------------------------------------------- /src/lib/connections/README: -------------------------------------------------------------------------------- 1 | Support for connection types is implemented by connection files in 2 | 3 | /usr/lib/netctl/connections/ 4 | 5 | The file name determines the name of the connection type, so support 6 | for the aviancarrier connection type will be provided by the file: 7 | 8 | /usr/lib/netctl/connections/aviancarrier 9 | 10 | Files that implement support for a connection type should NOT be 11 | executable. Such files should contain valid Bash code, among which two 12 | functions, namely _up and _down. For 13 | the aviancarrier file these would be: 14 | 15 | aviancarrier_up 16 | aviancarrier_down 17 | 18 | These functions are responsible for bringing the network up and down, 19 | respectively. When the functions are called, four bash files are 20 | already sourced, so all functions and variables in those files are 21 | available. The readily sourced files are: 22 | 23 | /usr/lib/netctl/network 24 | /usr/lib/netctl/globals 25 | /usr/lib/netctl/interface 26 | /etc/netctl/ 27 | 28 | Here, is the profile file specifying the desired network 29 | configuration. 30 | 31 | A simple example of a connection file is that of the dummy connection 32 | type. 33 | -------------------------------------------------------------------------------- /src/lib/connections/bond: -------------------------------------------------------------------------------- 1 | # Contributed by: andy123 2 | 3 | . "$SUBR_DIR/ip" 4 | 5 | # Make sure BindsToInterfaces is set 6 | BindsToInterfaces=("${BindsToInterfaces[@]}") 7 | 8 | bond_up() { 9 | if is_interface "$Interface"; then 10 | report_error "Interface '$Interface' already exists" 11 | return 1 12 | fi 13 | 14 | interface_add bond "$Interface" "$MACAddress" "" ${Mode:+mode "$Mode"} || return 15 | bring_interface_up "$Interface" 16 | for slave in "${BindsToInterfaces[@]}"; do 17 | ip link set dev "$slave" master "$Interface" 18 | done 19 | 20 | ip_set 21 | } 22 | 23 | bond_down() { 24 | for slave in "${BindsToInterfaces[@]}"; do 25 | ip link set dev "$slave" nomaster 26 | done 27 | 28 | ip_unset 29 | interface_delete "$Interface" 30 | } 31 | 32 | 33 | # vim: ft=sh ts=4 et sw=4: 34 | -------------------------------------------------------------------------------- /src/lib/connections/bridge: -------------------------------------------------------------------------------- 1 | # Contributed by: Thomas Bächler 2 | 3 | . "$SUBR_DIR/ip" 4 | 5 | # Make sure BindsToInterfaces is set 6 | BindsToInterfaces=("${BindsToInterfaces[@]}") 7 | 8 | bridge_up() { 9 | if is_interface "$Interface"; then 10 | if [[ ! -d "/sys/class/net/$Interface/brif" ]]; then 11 | report_error "Interface '$Interface' already exists and is not a bridge" 12 | return 1 13 | fi 14 | if [[ "$MACAddress" ]]; then 15 | report_error "Setting a MAC address on existing bridge interface '$Interface' is unsupported" 16 | fi 17 | else 18 | interface_add bridge "$Interface" "$MACAddress" || return 19 | fi 20 | 21 | for member in "${BindsToInterfaces[@]}"; do 22 | ip link set dev "$member" promisc on up 23 | ip addr flush dev "$member" scope host &>/dev/null 24 | ip addr flush dev "$member" scope site &>/dev/null 25 | ip addr flush dev "$member" scope global &>/dev/null 26 | ip link set dev "$member" master "$Interface" 27 | is_yes "${SkipForwardingDelay:-no}" && bridge link set dev "$member" state 3 28 | done 29 | 30 | bring_interface_up "$Interface" 31 | ip_set 32 | } 33 | 34 | bridge_down() { 35 | for member in "${BindsToInterfaces[@]}"; do 36 | ip link set dev "$member" promisc off down 37 | ip link set dev "$member" nomaster 38 | done 39 | 40 | ip_unset 41 | interface_delete "$Interface" 42 | } 43 | 44 | 45 | # vim: ft=sh ts=4 et sw=4: 46 | -------------------------------------------------------------------------------- /src/lib/connections/dummy: -------------------------------------------------------------------------------- 1 | # Contributed by: João Valverde 2 | 3 | . "$SUBR_DIR/ip" 4 | 5 | # Make sure BindsToInterfaces is set 6 | BindsToInterfaces=("${BindsToInterfaces[@]}") 7 | 8 | dummy_up() { 9 | if is_interface "$Interface"; then 10 | report_error "Interface '$Interface' already exists" 11 | return 1 12 | fi 13 | 14 | interface_add dummy "$Interface" "$MACAddress" || return 15 | bring_interface_up "$Interface" 16 | ip_set 17 | } 18 | 19 | dummy_down() { 20 | ip_unset 21 | interface_delete "$Interface" 22 | } 23 | 24 | 25 | # vim: ft=sh ts=4 et sw=4: 26 | -------------------------------------------------------------------------------- /src/lib/connections/ethernet: -------------------------------------------------------------------------------- 1 | # Ethernet connection support for netctl 2 | 3 | . "$SUBR_DIR/ip" 4 | 5 | 6 | ethernet_up() { 7 | if ! is_interface "$Interface"; then 8 | report_error "Interface '$Interface' does not exist" 9 | return 1 10 | fi 11 | 12 | # Disable IPv6 before bringing the interface up to prevent SLAAC 13 | if [[ $IP6 == "no" ]]; then 14 | sysctl -q -w "net.ipv6.conf.${Interface/.//}.disable_ipv6=1" 15 | fi 16 | 17 | if ! bring_interface_up "$Interface"; then 18 | report_error "Failed to bring interface '$Interface' up" 19 | return 1 20 | fi 21 | 22 | if is_yes "${SkipNoCarrier:-no}"; then 23 | SkipDAD=yes 24 | else 25 | # Some cards are plain slow to come up. Don't fail immediately. 26 | if ! timeout_wait "${TimeoutCarrier:-5}" '(( $(< "/sys/class/net/$Interface/carrier") ))'; then 27 | report_error "No connection found on interface '$Interface' (timeout)" 28 | bring_interface_down "$Interface" 29 | return 1 30 | fi 31 | fi 32 | 33 | 34 | if is_yes "${Auth8021X:-no}"; then 35 | . "$SUBR_DIR/wpa" 36 | : ${WPAConfigFile:=/etc/wpa_supplicant.conf} 37 | : ${WPADriver:=wired} 38 | : ${TimeoutWPA:=15} 39 | 40 | if ! wpa_start "$Interface" "$WPADriver" "$WPAConfigFile"; then 41 | report_error "The WPA supplicant did not start for interface '$Interface'" 42 | bring_interface_down "$Interface" 43 | return 1 44 | fi 45 | 46 | if ! wpa_wait_until_completed "$TimeoutWPA" "$Interface" "ASSOCIATED"; then 47 | wpa_stop "$Interface" 48 | bring_interface_down "$Interface" 49 | return 1 50 | fi 51 | fi 52 | 53 | if ! ip_set; then 54 | if is_yes "${Auth8021X:-no}"; then 55 | wpa_stop "$Interface" 56 | fi 57 | bring_interface_down "$Interface" 58 | return 1 59 | fi 60 | } 61 | 62 | ethernet_down() { 63 | ip_unset 64 | if is_yes "${Auth8021X:-no}"; then 65 | . "$SUBR_DIR/wpa" 66 | : ${WPAConfigFile:=/etc/wpa_supplicant.conf} 67 | do_debug wpa_stop "$Interface" 68 | fi 69 | bring_interface_down "$Interface" 70 | } 71 | 72 | 73 | # vim: ft=sh ts=4 et sw=4: 74 | -------------------------------------------------------------------------------- /src/lib/connections/macvlan: -------------------------------------------------------------------------------- 1 | # Contributed by: Walter F Dworak 2 | 3 | . "$SUBR_DIR/connections/ethernet" 4 | 5 | macvlan_up() { 6 | if [[ ${#BindsToInterfaces[@]} -ne 1 ]]; then 7 | report_error "No unique physical device for MACVLAN interface '$Interface' specified" 8 | return 1 9 | elif is_interface "$Interface"; then 10 | report_error "Interface '$Interface' already exists" 11 | return 1 12 | elif [[ $Mode != @(bridge|passthru|private|vepa) ]]; then 13 | report_error "Invalid mode '$Mode' for MACVLAN interface '$Interface'" 14 | return 1 15 | else 16 | bring_interface_up "$BindsToInterfaces" 17 | interface_add macvlan "$Interface" "$MACAddress" "$BindsToInterfaces" mode "$Mode" || return 18 | fi 19 | ethernet_up 20 | } 21 | 22 | macvlan_down() { 23 | ethernet_down 24 | interface_delete "$Interface" 25 | } 26 | 27 | 28 | # vim: ft=sh ts=4 et sw=4: 29 | -------------------------------------------------------------------------------- /src/lib/connections/mobile_ppp: -------------------------------------------------------------------------------- 1 | # Contributed by Robbie Smith 2 | # Based on Thomas Bächler’s pppoe script 3 | # Also see for more information. 4 | 5 | . "$SUBR_DIR/rfkill" 6 | 7 | : ${PPPD:=pppd} 8 | : ${InterfaceRoot=dev/} 9 | 10 | quote_word() { 11 | set -- "${@//\\/\\\\}" 12 | printf '"%s"\n' "${@//\"/\\\"}" 13 | } 14 | 15 | mobile_ppp_up() { 16 | local options_dir="$STATE_DIR/mobile_ppp-$Interface-$Profile" 17 | 18 | if [[ $RFKill ]]; then 19 | rf_enable "$Interface" "$RFKill" || return 1 20 | fi 21 | 22 | mkdir -p "$options_dir" 23 | if [[ -z $ChatScript ]]; then 24 | ChatScript="$options_dir/modem.chat" 25 | cat >> "$ChatScript" << EOF 26 | ECHO ON 27 | ABORT 'BUSY' 28 | ABORT 'NO CARRIER' 29 | ABORT 'VOICE' 30 | ABORT 'NO DIALTONE' 31 | ABORT 'NO DIAL TONE' 32 | ABORT 'NO ANSWER' 33 | ABORT 'DELAYED' 34 | ABORT '\nRINGING\r\n\r\nRINGING\r' 35 | REPORT CONNECT 36 | TIMEOUT 6 37 | '' 'ATQ0' 38 | 'OK-AT-OK' 'ATZ' 39 | TIMEOUT 3 40 | 'OK' 'AT+CFUN=1' 41 | 'OK' 'AT${Pin:++CPIN=$(quote_word "$Pin")}' 42 | 'OK\d-AT-OK' 'ATI' 43 | 'OK' 'ATZ' 44 | 'OK' '${Init:-ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0}' 45 | 'OK' 'AT$(case $Mode in 46 | 3Gonly) printf "\^SYSCFG=14,2,3fffffff,0,1";; 47 | 3Gpref) printf "\^SYSCFG=2,2,3fffffff,0,1";; 48 | GPRSonly) printf "\^SYSCFG=13,1,3fffffff,0,0";; 49 | GPRSpref) printf "\^SYSCFG=2,1,3fffffff,0,0";; 50 | SYSCFG=*) printf "\^$Mode";; 51 | # If set to "None", this is a no-op 52 | esac)' 53 | ${AccessPointName:+'OK-AT-OK' 'AT+CGDCONT=1,$(quote_word "IP"),$(quote_word "$AccessPointName")'} 54 | 'OK' 'ATDT${PhoneNumber:-*99#}' 55 | TIMEOUT 30 56 | CONNECT '' 57 | EOF 58 | fi 59 | 60 | cat >> "$options_dir/options" << EOF 61 | linkname $(quote_word "$Profile") 62 | ${PPPUnit:+unit $(quote_word "$PPPUnit")} 63 | $(quote_word "$Interface") 64 | 921600 65 | lock 66 | crtscts 67 | modem 68 | passive 69 | novj 70 | holdoff 10 71 | 72 | noauth 73 | noipdefault 74 | $(is_yes "${DefaultRoute:-yes}" || printf no)defaultroute 75 | maxfail $(quote_word "${MaxFail:-5}") 76 | $(is_yes "${UsePeerDNS:-yes}" && printf usepeerdns) 77 | hide-password 78 | ${User:+user $(quote_word "$User")} 79 | ${Password:+password $(quote_word "$Password")} 80 | connect $(quote_word "/usr/sbin/chat -v -t15 -f $(quote_word "$ChatScript")") 81 | ${OptionsFile:+file $(quote_word "$OptionsFile")} 82 | EOF 83 | 84 | network_ready 85 | if ! $PPPD file "$options_dir/options"; then 86 | rm -r "$options_dir" 87 | report_error "Could not establish a ppp connection for profile '$Profile'." 88 | return 1 89 | fi 90 | } 91 | 92 | mobile_ppp_down() { 93 | local options_dir pidfile pid 94 | options_dir="$STATE_DIR/mobile_ppp-$Interface-$Profile" 95 | pidfile="/var/run/ppp-$Profile.pid" 96 | 97 | if [[ -r $pidfile ]]; then 98 | read pid < "$pidfile" 99 | (( pid )) && kill "$pid" 100 | # Allow pppd up to one second to clean up 101 | timeout_wait 1 '[[ ! -f $pidfile ]]' 102 | fi 103 | 104 | rm -r "$options_dir" 105 | if [[ $RFKill ]]; then 106 | rf_disable "$Interface" "$RFKill" 107 | fi 108 | } 109 | 110 | 111 | # vim: ft=sh ts=4 et sw=4: 112 | -------------------------------------------------------------------------------- /src/lib/connections/openvswitch: -------------------------------------------------------------------------------- 1 | # Contributed by: Jonathan Hudson 2 | 3 | . "$SUBR_DIR/ip" 4 | 5 | : ${OVSCTL:=ovs-vsctl} 6 | 7 | # Make sure BindsToInterfaces is set 8 | BindsToInterfaces=("${BindsToInterfaces[@]}") 9 | 10 | openvswitch_up() { 11 | systemctl start ovs-vswitchd.service 12 | if ! $OVSCTL br-exists "$Interface" && ! $OVSCTL add-br "$Interface"; then 13 | report_error "Could not create a bridge named '$Interface'" 14 | return 1 15 | fi 16 | 17 | for port in "${BindsToInterfaces[@]}"; do 18 | ip link set dev "$port" promisc on up 19 | ip addr flush dev "$port" scope host &>/dev/null 20 | ip addr flush dev "$port" scope site &>/dev/null 21 | ip addr flush dev "$port" scope global &>/dev/null 22 | $OVSCTL --may-exist add-port "$Interface" "$port" 23 | done 24 | 25 | bring_interface_up "$Interface" 26 | ip_set 27 | } 28 | 29 | openvswitch_down() { 30 | for port in "${BindsToInterfaces[@]}"; do 31 | ip link set dev "$port" promisc off down 32 | done 33 | 34 | ip_unset 35 | $OVSCTL del-br "$Interface" 36 | } 37 | 38 | 39 | # vim: ft=sh ts=4 et sw=4: 40 | -------------------------------------------------------------------------------- /src/lib/connections/ppp: -------------------------------------------------------------------------------- 1 | . "$SUBR_DIR/connections/pppoe" 2 | 3 | ppp_compatible() { 4 | if [[ ${#BindsToInterfaces[@]} -ne 1 ]]; then 5 | report_error "No unique port for PPP interface '$Interface' specified" 6 | return 1 7 | fi 8 | if [[ ! $Interface =~ ppp([[:digit:]]+) ]]; then 9 | report_error "Interface '$Interface' is not of the supported form 'ppp'" 10 | return 1 11 | fi 12 | PPPUnit=${BASH_REMATCH[1]} 13 | echo "$BindsToInterfaces" 14 | } 15 | 16 | ppp_up() { 17 | local interface 18 | interface=$(ppp_compatible) || return 1 19 | 20 | Interface=$interface pppoe_up 21 | } 22 | 23 | ppp_down() { 24 | local interface 25 | interface=$(ppp_compatible) || return 1 26 | 27 | Interface=$interface pppoe_down 28 | } 29 | 30 | 31 | # vim: ft=sh ts=4 et sw=4: 32 | -------------------------------------------------------------------------------- /src/lib/connections/pppoe: -------------------------------------------------------------------------------- 1 | # Contributed by: Thomas Bächler 2 | 3 | : ${PPPD:=pppd} 4 | 5 | quote_word() { 6 | set -- "${@//\\/\\\\}" 7 | printf '"%s"\n' "${@//\"/\\\"}" 8 | } 9 | 10 | pppoe_up() { 11 | local options="$STATE_DIR/pppoe-$Interface-$Profile/options" 12 | 13 | if ! is_interface "$Interface"; then 14 | report_error "Interface '$Interface' does not exist" 15 | return 1 16 | fi 17 | if ! bring_interface_up "$Interface"; then 18 | report_error "Failed to bring interface '$Interface' up" 19 | return 1 20 | fi 21 | 22 | mkdir -p "$(dirname "$options")" 23 | cat >> "$options" << EOF 24 | linkname $(quote_word "$Profile") 25 | ${PPPUnit:+unit $(quote_word "$PPPUnit")} 26 | updetach 27 | plugin pppoe.so 28 | nic-$Interface 29 | 30 | noauth 31 | $(is_yes "${DefaultRoute:-yes}" || printf no)defaultroute 32 | maxfail $(quote_word "${MaxFail:-5}") 33 | $(is_yes "${UsePeerDNS:-yes}" && printf usepeerdns) 34 | $(quote_word "${ConnectionMode:-persist}") 35 | $([[ $ConnectionMode == demand ]] && printf "idle %s" "$(quote_word "$IdleTimeout")") 36 | ${LCPEchoInterval:+lcp-echo-interval $(quote_word "$LCPEchoInterval")} 37 | ${LCPEchoFailure:+lcp-echo-failure $(quote_word "$LCPEchoFailure")} 38 | ${PPPoEService:+rp_pppoe_service $(quote_word "$PPPoEService")} 39 | ${PPPoEAC:+rp_pppoe_ac $(quote_word "$PPPoEAC")} 40 | ${PPPoESession:+rp_pppoe_sess $(quote_word "$PPPoESession")} 41 | ${PPPoEMAC:+pppoe-mac $(quote_word "$PPPoEMAC")} 42 | $(is_yes "${PPPoEIP6:-no}" && printf +ipv6) 43 | $(is_yes "${PPPoEIP6:-yes}" || printf noipv6) 44 | 45 | user $(quote_word "$User") 46 | password $(quote_word "$Password") 47 | ${OptionsFile:+file $(quote_word "$OptionsFile")} 48 | EOF 49 | 50 | network_ready 51 | if ! $PPPD file "$options"; then 52 | rm "$options" 53 | rmdir "$(dirname "$options")" 54 | 55 | bring_interface_down "$Interface" 56 | 57 | report_error "Could not establish a ppp connection for profile '$Profile'." 58 | return 1 59 | fi 60 | } 61 | 62 | pppoe_down() { 63 | local options pidfile pid 64 | options="$STATE_DIR/pppoe-$Interface-$Profile/options" 65 | pidfile="/var/run/ppp-$Profile.pid" 66 | 67 | if [[ -r $pidfile ]]; then 68 | read pid < "$pidfile" 69 | (( pid )) && kill "$pid" 70 | # Allow pppd up to one second to clean up 71 | timeout_wait 1 '[[ ! -f $pidfile ]]' 72 | fi 73 | 74 | rm "$options" 75 | rmdir "$(dirname "$options")" 76 | 77 | bring_interface_down "$Interface" 78 | } 79 | 80 | 81 | # vim: ft=sh ts=4 et sw=4: 82 | -------------------------------------------------------------------------------- /src/lib/connections/tunnel: -------------------------------------------------------------------------------- 1 | # Contributed by: Kyle Fuller 2 | 3 | . "$SUBR_DIR/ip" 4 | 5 | # Make sure BindsToInterfaces is set 6 | BindsToInterfaces=("${BindsToInterfaces[@]}") 7 | 8 | tunnel_up() { 9 | local family="-4" 10 | 11 | if is_interface "$Interface"; then 12 | report_error "Interface '$Interface' already exists" 13 | return 1 14 | fi 15 | 16 | [[ $Mode == *ip6* || $Mode == "any" ]] && family="-6" 17 | do_debug ip "$family" tunnel add "$Interface" mode "$Mode" \ 18 | remote "$Remote" ${Local:+local "$Local"} ${Key:+key "$Key"} || return 19 | 20 | bring_interface_up "$Interface" 21 | ip_set 22 | } 23 | 24 | tunnel_down() { 25 | ip_unset 26 | bring_interface_down "$Interface" 27 | ip tunnel delete "$Interface" 28 | } 29 | 30 | 31 | # vim: ft=sh ts=4 et sw=4: 32 | -------------------------------------------------------------------------------- /src/lib/connections/tuntap: -------------------------------------------------------------------------------- 1 | # Contributed by: Rémy Oudompheng 2 | 3 | . "$SUBR_DIR/ip" 4 | 5 | # Make sure BindsToInterfaces is set 6 | BindsToInterfaces=("${BindsToInterfaces[@]}") 7 | 8 | tuntap_up() { 9 | if is_interface "$Interface"; then 10 | report_error "Interface '$Interface' already exists" 11 | return 1 12 | fi 13 | 14 | do_debug ip tuntap add dev "$Interface" mode "$Mode" \ 15 | ${User:+user "$User"} ${Group:+group "$Group"} || return 16 | 17 | bring_interface_up "$Interface" 18 | IP=${IP-no} ip_set 19 | } 20 | 21 | tuntap_down() { 22 | ip_unset 23 | bring_interface_down "$Interface" 24 | ip tuntap delete dev "$Interface" mode "$Mode" 25 | } 26 | 27 | 28 | # vim: ft=sh ts=4 et sw=4: 29 | -------------------------------------------------------------------------------- /src/lib/connections/vlan: -------------------------------------------------------------------------------- 1 | # Contributed by: Thomas S Hatch 2 | 3 | . "$SUBR_DIR/connections/ethernet" 4 | 5 | vlan_up() { 6 | if [[ ${#BindsToInterfaces[@]} -ne 1 ]]; then 7 | report_error "No unique physical device for VLAN interface '$Interface' specified" 8 | return 1 9 | elif is_interface "$Interface"; then 10 | report_error "Interface '$Interface' already exists" 11 | return 1 12 | elif [[ $VLANID != +([[:digit:]]) ]]; then 13 | report_error "Invalid VLAN identifier: '$VLANID'" 14 | return 1 15 | else 16 | bring_interface_up "$BindsToInterfaces" 17 | interface_add vlan "$Interface" "$MACAddress" "$BindsToInterfaces" id "$VLANID" || return 18 | fi 19 | 20 | ethernet_up 21 | } 22 | 23 | vlan_down() { 24 | ethernet_down 25 | interface_delete "$Interface" 26 | } 27 | 28 | 29 | # vim: ft=sh ts=4 et sw=4: 30 | -------------------------------------------------------------------------------- /src/lib/connections/wireguard: -------------------------------------------------------------------------------- 1 | # Contributed by: Thibaut Sautereau 2 | 3 | . "$SUBR_DIR/ip" 4 | 5 | # Make sure BindsToInterfaces is set 6 | BindsToInterfaces=("${BindsToInterfaces[@]}") 7 | 8 | wireguard_up() { 9 | if is_interface "$Interface"; then 10 | report_error "Interface '$Interface' already exists" 11 | return 1 12 | fi 13 | 14 | # Treat $MACAddress as in other connections, but it has no effect here 15 | interface_add wireguard "$Interface" "$MACAddress" || return 16 | wg setconf "$Interface" "${WGConfigFile:-/etc/wireguard/$Interface.conf}" 17 | bring_interface_up "$Interface" 18 | ip_set 19 | } 20 | 21 | wireguard_down() { 22 | ip_unset 23 | interface_delete "$Interface" 24 | } 25 | 26 | 27 | # vim: ft=sh ts=4 et sw=4: 28 | -------------------------------------------------------------------------------- /src/lib/connections/wireless: -------------------------------------------------------------------------------- 1 | # Wireless connection support for netctl 2 | 3 | . "$SUBR_DIR/ip" 4 | . "$SUBR_DIR/wpa" 5 | . "$SUBR_DIR/rfkill" 6 | 7 | 8 | wireless_up() { 9 | local config_file 10 | 11 | if ! is_interface "$Interface"; then 12 | report_error "Interface '$Interface' does not exist" 13 | return 1 14 | fi 15 | 16 | # Default settings 17 | : ${Security:=none} 18 | : ${WPADriver:=nl80211,wext} 19 | : ${TimeoutWPA:=15} 20 | 21 | if [[ $RFKill ]]; then 22 | rf_enable "$Interface" "$RFKill" || return 1 23 | fi 24 | 25 | # Kill any lingering WPA supplicants 26 | WPAConfigFile="" wpa_stop "$Interface" &> /dev/null 27 | 28 | if [[ $Security == "wpa-config" ]]; then 29 | : ${WPAConfigFile:=/etc/wpa_supplicant.conf} 30 | config_file=$WPAConfigFile 31 | else 32 | # Remove any stray configuration files 33 | wpa_destroy_config_file "$Interface" 34 | config_file=$(wpa_make_config_file "$Interface") 35 | if [[ -z $config_file ]]; then 36 | report_error "Could not create a WPA config file for interface '$Interface'" 37 | return 1 38 | fi 39 | printf '%s\n' "network={" "$(wpa_make_config_block)" "}" >> "$config_file" 40 | fi 41 | 42 | # Start the WPA supplicant 43 | if ! wpa_start "$Interface" "$WPADriver" "$config_file"; then 44 | report_error "The WPA supplicant did not start for interface '$Interface'" 45 | if [[ $Security != "wpa-config" ]]; then 46 | wpa_destroy_config_file "$Interface" 47 | fi 48 | bring_interface_down "$Interface" 49 | return 1 50 | fi 51 | 52 | network_ready 53 | # Bring interface up after starting wpa_supplicant 54 | # This is important since cards such as iwl3945 do not support 55 | # mode switching when they are already up. 56 | if ! bring_interface_up "$Interface" || 57 | ! wpa_wait_until_completed "$TimeoutWPA" "$Interface" || 58 | ! ip_set; then 59 | wpa_stop "$Interface" 60 | if [[ $Security != "wpa-config" ]]; then 61 | wpa_destroy_config_file "$Interface" 62 | fi 63 | bring_interface_down "$Interface" 64 | return 1 65 | fi 66 | } 67 | 68 | wireless_down() { 69 | ip_unset 70 | if [[ $Security == "wpa-config" ]]; then 71 | : ${WPAConfigFile:=/etc/wpa_supplicant.conf} 72 | else 73 | wpa_destroy_config_file "$Interface" 74 | fi 75 | wpa_stop "$Interface" 76 | bring_interface_down "$Interface" || return 1 77 | if [[ $RFKill ]]; then 78 | rf_disable "$Interface" "$RFKill" 79 | fi 80 | } 81 | 82 | 83 | # vim: ft=sh ts=4 et sw=4: 84 | -------------------------------------------------------------------------------- /src/lib/dhcp/README: -------------------------------------------------------------------------------- 1 | Support for dhcp clients is implemented by files in 2 | 3 | /usr/lib/netctl/dhcp/ 4 | 5 | The file name determines the name of the client for the profile, so 6 | support for a client named dhcpcd is provided by the file: 7 | 8 | /usr/lib/netctl/dhcp/dhcpcd 9 | 10 | Files that implement support for a connection type should NOT be 11 | executable. Such files should contain valid Bash code, among which two 12 | functions, namely _start and _stop. For 13 | the client named dhcpcd these would be: 14 | 15 | dhcpcd_start 16 | dhcpcd_stop 17 | 18 | These functions are responsible for starting and stopping the dhcp 19 | client. When the functions are called, four bash files are already 20 | sourced, so all functions and variables in those files are available. 21 | The readily sourced files are: 22 | 23 | /usr/lib/netctl/network 24 | /usr/lib/netctl/globals 25 | /usr/lib/netctl/interface 26 | /etc/netctl/ 27 | 28 | Here, is the profile file specifying the desired network 29 | configuration. 30 | 31 | When called, the start and stop functions get as their first argument 32 | the version of the IP protocol that the dhcp client is expected to use. 33 | In the case of starting the client for IPv6, an additional second 34 | argument 'noaddr' may be supplied, which indicates that the dhcp client 35 | should configure everything but an IP address. 36 | -------------------------------------------------------------------------------- /src/lib/dhcp/dhclient: -------------------------------------------------------------------------------- 1 | type dhclient &> /dev/null || return 2 | 3 | dhclient_start() { 4 | local options pidfile="/run/dhclient-$Interface-$1.pid" 5 | case $1 in 6 | 4) options=$DhclientOptions;; 7 | 6) options=$DhclientOptions6;; 8 | *) return 1;; 9 | esac 10 | [[ $2 == "noaddr" ]] && options+=" -S" 11 | if ! do_debug do_readable dhclient "-$1" -q -e "TIMEOUT=${TimeoutDHCP:-30}" -pf "$pidfile" $options "$Interface"; then 12 | report_error "DHCP IPv$1 lease attempt failed on interface '$Interface'" 13 | return 1 14 | fi 15 | } 16 | 17 | dhclient_stop() { 18 | local stop="-x" pidfile="/run/dhclient-$Interface-$1.pid" 19 | if [[ -f $pidfile ]]; then 20 | is_yes "${DHCPReleaseOnStop:-no}" && stop="-r" 21 | do_debug dhclient "-$1" -q $stop "$Interface" -pf "$pidfile" > /dev/null 22 | fi 23 | } 24 | 25 | 26 | # vim: ft=sh ts=4 et sw=4: 27 | -------------------------------------------------------------------------------- /src/lib/dhcp/dhcpcd: -------------------------------------------------------------------------------- 1 | type dhcpcd &> /dev/null || return 2 | 3 | dhcpcd_start() { 4 | local options 5 | case $1 in 6 | 4) options=${DhcpcdOptions-"-L"};; 7 | 6) options=$DhcpcdOptions6;; 8 | *) return 1;; 9 | esac 10 | [[ $2 == "noaddr" ]] && options+=" --inform6" 11 | # If using own dns, tell dhcpcd to NOT replace resolv.conf 12 | [[ $DNS ]] && options+=" -C resolv.conf" 13 | if ! do_debug do_readable dhcpcd "-$1" -q -t "${TimeoutDHCP:-30}" $options "$Interface"; then 14 | report_error "DHCP IPv$1 lease attempt failed on interface '$Interface'" 15 | return 1 16 | fi 17 | } 18 | 19 | dhcpcd_stop() { 20 | local stop="-x" 21 | if [[ -f "/run/dhcpcd/$Interface-$1.pid" ]]; then 22 | is_yes "${DHCPReleaseOnStop:-no}" && stop="-k" 23 | do_debug dhcpcd "-$1" -q $stop "$Interface" > /dev/null 24 | fi 25 | } 26 | 27 | 28 | # vim: ft=sh ts=4 et sw=4: 29 | -------------------------------------------------------------------------------- /src/lib/globals: -------------------------------------------------------------------------------- 1 | NETCTL_VERSION="notpackaged" 2 | PROFILE_DIR="/etc/netctl" 3 | SUBR_DIR="/usr/lib/netctl" 4 | STATE_DIR="/run/netctl" 5 | STATE_FILE="${NETCTL_STATE_FILE:-/var/lib/netctl/netctl.state}" 6 | 7 | 8 | ### Logging/Error reporting 9 | 10 | report_notice() { 11 | printf '%s\n' "$*" 12 | } 13 | 14 | report_error() { 15 | local prefix="<3>" suffix="" 16 | if [[ -t 2 ]]; then 17 | prefix=$(tput bold; tput setaf 1) 18 | suffix=$(tput sgr0) 19 | fi 20 | printf '%s%s%s\n' "$prefix" "$*" "$suffix" >&2 21 | } 22 | 23 | report_debug() { 24 | is_yes "${NETCTL_DEBUG:-no}" && printf 'DEBUG: %s\n' "$*" >&2 25 | } 26 | 27 | exit_error() { 28 | report_error "$@" 29 | exit 1 30 | } 31 | 32 | 33 | ### Variable management 34 | 35 | ## Check if a variable occurs in an array 36 | # $1: the variable to find 37 | # $2...: the array elements 38 | in_array() { 39 | local hay needle=$1 40 | shift 41 | for hay; do 42 | [[ $hay == "$needle" ]] && return 0 43 | done 44 | return 1 45 | } 46 | 47 | ## Check if a variable denotes a positive truth value 48 | # $1: the variable to check, use is_yes "${VAR:-yes}" to set a default 49 | is_yes() { 50 | case ${1,,} in 51 | yes|true|on|1) 52 | return 0 53 | ;; 54 | no|false|off|0) 55 | return 1 56 | ;; 57 | *) 58 | report_error "Not a valid truth value: '$1'" 59 | return 2 60 | ;; 61 | esac 62 | } 63 | 64 | 65 | ### Control flow 66 | 67 | ## Show what we evaluate when debugging, but always evaluate 68 | do_debug() { 69 | report_debug "${FUNCNAME[1]}:" "$@" 70 | "$@" 71 | } 72 | 73 | ## Evaluate with a permissive umask 74 | do_readable() { 75 | local result 76 | umask 022 77 | "$@" 78 | result=$? 79 | umask 077 80 | return $result 81 | } 82 | 83 | ## Exit if we are not effectively root 84 | # $1: program name (optional) 85 | ensure_root() { 86 | (( EUID == 0 )) || exit_error "${1-$0} needs root privileges" 87 | } 88 | 89 | ## Waits until a statement succeeds or a timeout occurs 90 | # $1: timeout in seconds 91 | # $2...: condition command 92 | timeout_wait() { 93 | local timeout=$1 94 | (( timeout *= 5 )) 95 | shift 96 | until eval "$@"; do 97 | (( timeout-- > 0 )) || return 1 98 | sleep 0.2 99 | done 100 | return 0 101 | } 102 | 103 | 104 | ### Profile management 105 | 106 | ## Load all available hooks 107 | load_hooks() { 108 | local hook 109 | while IFS= read -r hook; do 110 | source "$hook" 111 | done < <(find -L "$PROFILE_DIR/hooks" -maxdepth 1 -type f -executable -not -name '.*' -not -name '*~' -not -name $'*\n*' | sort) 112 | } 113 | 114 | ## Load interface configuration, if present 115 | # $1: interface name 116 | load_interface_config() { 117 | local config_file="$PROFILE_DIR/interfaces/$1" 118 | if [[ -x $config_file ]]; then 119 | source "$config_file" 120 | fi 121 | } 122 | 123 | ## Sources all hooks and a profile (but no interface configuration) 124 | # $1: profile name 125 | load_profile() { 126 | # Expose the profile name 127 | Profile=$1 128 | if [[ -z $Profile || ! -r "$PROFILE_DIR/$Profile" ]]; then 129 | exit_error "Profile '$Profile' does not exist or is not readable" 130 | fi 131 | load_hooks 132 | source "$PROFILE_DIR/$Profile" 133 | if [[ -z $Interface ]]; then 134 | exit_error "Profile '$Profile' does not specify an interface" 135 | fi 136 | load_interface_config "$Interface" 137 | if [[ ! -r "${Connection:+$SUBR_DIR/connections/$Connection}" ]]; then 138 | exit_error "Profile '$Profile' does not specify a valid connection" 139 | fi 140 | source "$SUBR_DIR/connections/$Connection" 141 | } 142 | 143 | ## List all acceptable profiles names separated by newlines 144 | list_profiles() { 145 | # Follow aliases with -L, skip forbidden/reserved names 146 | find -L "$PROFILE_DIR/" -maxdepth 1 -type f -not -name '.*' -not -name '*~' -not -name $'*\n*' -not -name '*.action' -not -name '*.conf' -not -name '*.service' -printf '%f\n' 147 | } 148 | 149 | ## List names of profiles for a given interface and/or connection 150 | # $1: interface (optional) 151 | # $2: connection (optional) 152 | filter_profiles() { 153 | list_profiles | while IFS= read -r Profile; do 154 | if ( 155 | source "$PROFILE_DIR/$Profile" &> /dev/null 156 | [[ $Interface && ( -z $1 || $1 == "$Interface" ) ]] || exit 157 | load_interface_config "$Interface" > /dev/null 158 | [[ $Connection && ( -z $2 || $2 == "$Connection" ) ]] || exit 159 | ); then 160 | printf '%s\n' "$Profile" 161 | fi 162 | done 163 | } 164 | 165 | ## Exit if a profile file is not syntactically correct 166 | # $1: profile name 167 | verify_profile() { 168 | /bin/bash -n "$PROFILE_DIR/$1" || exit 1 169 | } 170 | 171 | ## Wrapper around systemctl converting profile names to unit names 172 | # $1: systemctl command 173 | # $2...: profile names 174 | sd_call() { 175 | local command=$1 176 | shift 177 | systemctl $command $(systemd-escape --template=netctl@.service "$@") 178 | } 179 | 180 | ## Retrieves the status string from the unit for a profile 181 | # $1: profile name 182 | sd_status_text() { 183 | sd_call "show --property=StatusText --value" "$1" 184 | } 185 | 186 | 187 | # Set a restrictive umask 188 | do_readable : 189 | 190 | 191 | # vim: ft=sh ts=4 et sw=4: 192 | -------------------------------------------------------------------------------- /src/lib/interface: -------------------------------------------------------------------------------- 1 | ## /usr/lib/netctl/globals needs to be sourced before this file 2 | 3 | 4 | ## Check if a string represents a network interface 5 | # $1: potential interface name 6 | is_interface() { 7 | # Strip any old school alias specifier 8 | [[ -d "/sys/class/net/${1%%:?*}" ]] 9 | } 10 | 11 | ## Add an interface 12 | # $1: interface type 13 | # $2: interface name 14 | # $3: interface MAC address (optional) 15 | # $4: interface link (optional) 16 | # $5...: additional type related arguments 17 | interface_add() { 18 | local type="$1" name="$2" address="$3" link="$4" 19 | if [[ -e "/sys/class/net/$address/address" ]]; then 20 | address=$(< "/sys/class/net/$address/address") 21 | fi 22 | do_debug ip link add ${link:+link "$link"} name "$name" ${address:+address "$address"} type "$type" "${@:5}" $LinkOptions || return 23 | load_interface_config "$name" 24 | } 25 | 26 | ## Delete an interface 27 | # $1: interface name 28 | interface_delete() { 29 | bring_interface_down "$1" 30 | ip link delete "$1" 31 | } 32 | 33 | ## Check if an interface is up 34 | # $1: interface name 35 | interface_is_up() { 36 | local flags 37 | read flags < "/sys/class/net/${1%%:?*}/flags" 38 | # IFF_UP is defined as 0x1 in linux/if.h 39 | (( flags & 0x1 )) 40 | } 41 | 42 | ## Activate an interface 43 | # $1: interface name 44 | bring_interface_up() { 45 | local interface=$1 46 | ip link set dev "$interface" up &>/dev/null 47 | timeout_wait "${TimeoutUp:-5}" 'interface_is_up "$interface"' 48 | } 49 | 50 | ## Deactivate an interface 51 | # $1: interface name 52 | bring_interface_down() { 53 | local interface=$1 54 | ip link set dev "$interface" down &>/dev/null 55 | # We reuse the up timeout (down normally is faster) 56 | timeout_wait "${TimeoutUp:-5}" '! interface_is_up "$interface"' 57 | } 58 | 59 | 60 | # vim: ft=sh ts=4 et sw=4: 61 | -------------------------------------------------------------------------------- /src/lib/ip: -------------------------------------------------------------------------------- 1 | ## /usr/lib/netctl/globals needs to be sourced before this file 2 | 3 | 4 | ## Interface a DHCP client 5 | # $1: DHCP client 6 | # $2: command 7 | # $3...: additional arguments 8 | dhcp_call() { 9 | local client="$1" command="$2" 10 | shift 2 11 | 12 | if [[ ! -r "$SUBR_DIR/dhcp/$client" ]]; then 13 | report_error "DHCP client '$client' is unsupported" 14 | return 127 15 | fi 16 | if ! source "$SUBR_DIR/dhcp/$client"; then 17 | report_error "DHCP client '$client' is not installed or not ready" 18 | return 127 19 | fi 20 | "${client}_$command" "$@" 21 | } 22 | 23 | 24 | ## Add resolv.conf entries for an interface 25 | # $1: interface name 26 | # $2...: entries, one line per variable 27 | resolvconf_add() { 28 | local interface="$1" 29 | shift 30 | printf '%s\n' "$@" | do_readable resolvconf -a "$interface" 31 | } 32 | 33 | 34 | ## Set up an IP configuration 35 | # $Interface: interface name 36 | # $IP: type of IPv4 configuration 37 | # $IP6: type of IPv6 configuration 38 | ip_set() { 39 | local addr line route interface_sysctl=${Interface/.//} 40 | 41 | network_ready 42 | 43 | if [[ -z $IP && -z $IP6 ]]; then 44 | report_error "Neither IP, nor IP6 was specified" 45 | return 1 46 | fi 47 | 48 | # Load ipv6 module if necessary 49 | case "$IP6" in 50 | dhcp|dhcp-noaddr|stateless|static) 51 | [[ -d "/proc/sys/net/ipv6" ]] || modprobe ipv6 52 | sysctl -q -w "net.ipv6.conf.$interface_sysctl.disable_ipv6=0" 53 | if [[ $IP6 == "static" ]]; then 54 | sysctl -q -w "net.ipv6.conf.$interface_sysctl.accept_ra=0" 55 | else # Accept router advertisements regardless of the forwarding setting 56 | sysctl -q -w "net.ipv6.conf.$interface_sysctl.accept_ra=2" 57 | fi 58 | ;; 59 | no) 60 | [[ -d "/proc/sys/net/ipv6" ]] && sysctl -q -w "net.ipv6.conf.$interface_sysctl.disable_ipv6=1" 61 | ;; 62 | "") # Having IP6= unset does not prevent router advertisements from being received 63 | ;; 64 | *) 65 | report_error "IP6 must be 'dhcp', 'dhcp-noaddr', 'stateless', 'static' or 'no'" 66 | return 1 67 | ;; 68 | esac 69 | 70 | case $IP in 71 | dhcp) 72 | dhcp_call "${DHCPClient:-dhcpcd}" start 4 || return 73 | ;; 74 | static) 75 | for addr in "${Address[@]}"; do 76 | if ! do_debug ip addr add "$addr" brd + dev "$Interface"; then 77 | report_error "Could not add address '$addr' to interface '$Interface'" 78 | return 1 79 | fi 80 | done 81 | ;; 82 | ""|no) 83 | ;; 84 | *) 85 | report_error "IP must be either 'dhcp', 'static' or 'no'" 86 | return 1 87 | ;; 88 | esac 89 | 90 | if [[ $IP != @(|no) ]]; then 91 | # Add static IP routes 92 | for route in "${Routes[@]}"; do 93 | if ! do_debug ip route add $route dev "$Interface"; then 94 | report_error "Could not add route '$route' to interface '$Interface'" 95 | return 1 96 | fi 97 | done 98 | 99 | # Set a custom gateway after static routes are added 100 | if [[ $IP == "static" && $Gateway ]]; then 101 | if ! do_debug ip route add default via "$Gateway" dev "$Interface"; then 102 | report_error "Could not set gateway '$Gateway' on interface '$Interface'" 103 | return 1 104 | fi 105 | fi 106 | fi 107 | 108 | if [[ $IP6 != @(|no) ]]; then 109 | if [[ $IP6 == @(stateless|static) ]]; then 110 | for addr in "${Address6[@]}"; do 111 | if ! do_debug ip -6 addr add $addr $(is_yes "${SkipDAD:-no}" && printf nodad) dev "$Interface"; then 112 | report_error "Could not add address '$addr' to interface '$Interface'" 113 | fi 114 | done 115 | fi 116 | 117 | if ! is_yes "${SkipDAD:-no}"; then 118 | # Wait for Duplicate Address Detection to finish 119 | if ! timeout_wait "${TimeoutDAD:-3}" '[[ -z "$(ip -6 addr show dev "$Interface" tentative)" ]]'; then 120 | report_error "Duplicate Address Detection is taking too long on interface '$Interface'" 121 | return 1 122 | fi 123 | fi 124 | 125 | # Start a DHCPv6 client after DAD has finished for the link-local address 126 | if [[ $IP6 == @(dhcp|dhcp-noaddr) ]]; then 127 | dhcp_call "${DHCP6Client:-dhclient}" start 6 ${IP6:5} || return 128 | fi 129 | 130 | # Add static IPv6 routes after DAD has finished 131 | for route in "${Routes6[@]}"; do 132 | if ! do_debug ip -6 route add $route dev "$Interface"; then 133 | report_error "Could not add route '$route' to interface '$Interface'" 134 | return 1 135 | fi 136 | done 137 | 138 | # Set a custom gateway after static routes are added 139 | if [[ $IP6 == @(stateless|static) && $Gateway6 ]]; then 140 | if ! do_debug ip -6 route replace default via "$Gateway6" dev "$Interface"; then 141 | report_error "Could not set gateway '$Gateway6' on interface '$Interface'" 142 | return 1 143 | fi 144 | fi 145 | fi 146 | 147 | for line in "${IPCustom[@]}"; do 148 | if ! do_debug ip $line; then 149 | report_error "Could not configure interface ($line)" 150 | return 1 151 | fi 152 | done 153 | 154 | if [[ $Hostname ]]; then 155 | if ! do_debug hostnamectl --transient set-hostname "$Hostname"; then 156 | report_error "Cannot set the hostname to '$Hostname'" 157 | return 1 158 | fi 159 | fi 160 | 161 | if [[ $DNS ]]; then 162 | resolvconf_add "$Interface" \ 163 | "${DNSDomain/#/domain }" \ 164 | "${DNSSearch/#/search }" \ 165 | "${DNS[@]/#/nameserver }" \ 166 | "${DNSOptions[@]/#/options }" 167 | fi 168 | } 169 | 170 | 171 | ## Clean up the IP configuration 172 | # $Interface: interface name 173 | # $IP: type of IPv4 configuration 174 | # $IP6: type of IPv6 configuration 175 | ip_unset() { 176 | [[ $IP == "dhcp" ]] && dhcp_call "${DHCPClient:-dhcpcd}" stop 4 177 | [[ $IP6 == dhcp* ]] && dhcp_call "${DHCP6Client:-dhclient}" stop 6 178 | [[ $Hostname ]] && do_debug hostnamectl --transient set-hostname "" 179 | [[ $DNS ]] && resolvconf -d "$Interface" 180 | ip route flush dev "$Interface" &>/dev/null 181 | ip -6 route flush dev "$Interface" &>/dev/null 182 | ip addr flush dev "$Interface" scope host &>/dev/null 183 | ip addr flush dev "$Interface" scope site &>/dev/null 184 | ip addr flush dev "$Interface" scope global &>/dev/null 185 | } 186 | 187 | 188 | # vim: ft=sh ts=4 et sw=4: 189 | -------------------------------------------------------------------------------- /src/lib/network: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | . /usr/lib/netctl/globals 4 | . "$SUBR_DIR/interface" 5 | 6 | 7 | ## Indicate that the network stack for the profile is up 8 | network_ready() { 9 | if ! is_yes "${WaitOnline:-no}" && ! is_yes "${NETWORK_READY:-no}"; then 10 | do_debug systemd-notify --ready 11 | NETWORK_READY=yes 12 | fi 13 | } 14 | 15 | ## Describe the status of the service for the profile 16 | # $1: status string, should be "online" when the profile gets connected 17 | network_status() { 18 | do_debug systemd-notify --status="$1" 19 | if [[ $1 == "online" ]] && is_yes "${WaitOnline:-no}"; then 20 | WaitOnline=no network_ready 21 | fi 22 | } 23 | 24 | ## Start the loaded profile 25 | network_start() { 26 | report_notice "Starting network profile '$Profile'..." 27 | if is_interface "$Interface" && interface_is_up "$Interface" && \ 28 | ! is_yes "${ForceConnect:-no}"; then 29 | report_error "The interface of network profile '$Profile' is already up" 30 | exit 1 31 | fi 32 | if ! "${Connection}_up"; then 33 | report_error "Failed to bring the network up for profile '$Profile'" 34 | exit 1 35 | fi 36 | network_ready 37 | # Sandbox the eval 38 | if ! ( do_debug eval "$ExecUpPost" ); then 39 | report_error "ExecUpPost failed for network profile '$Profile'" 40 | # Failing ExecUpPost will take the connection down 41 | "${Connection}_down" 42 | exit 1 43 | fi 44 | network_status "online" 45 | report_notice "Started network profile '$Profile'" 46 | } 47 | 48 | ## Stop the loaded profile 49 | network_stop() { 50 | report_notice "Stopping network profile '$Profile'..." 51 | # Sandbox the eval 52 | if ! ( do_debug eval "$ExecDownPre" ); then 53 | report_error "ExecDownPre failed for network profile '$Profile'" 54 | # Failing ExecDownPre will leave the profile active 55 | exit 1 56 | fi 57 | if ! "${Connection}_down"; then 58 | report_error "Failed to bring the network down for profile '$Profile'" 59 | exit 1 60 | fi 61 | network_status "" 62 | if is_interface "$Interface" && interface_is_up "$Interface" && \ 63 | ! is_yes "${ForceConnect:-no}"; then 64 | report_error "The interface of network profile '$Profile' did not go down" 65 | exit 1 66 | fi 67 | report_notice "Stopped network profile '$Profile'" 68 | } 69 | 70 | ## Wait for all enabled profiles to come online within a single timeout 71 | network_wait_online() { 72 | mapfile -t Profiles < <(list_profiles) 73 | i=0 74 | timeout_wait "${TIMEOUT_ONLINE:-120}" \ 75 | '! until [[ $(sd_call is-enabled "${Profiles[i]}") == "enabled" && 76 | $(sd_status_text "${Profiles[i]}") != "online" ]]; do 77 | (( ++i < ${#Profiles[@]} )) || return 0; done' 78 | } 79 | 80 | 81 | ensure_root netctl 82 | # Ensure we are not in a transient directory 83 | cd / 84 | 85 | if [[ $# -eq 1 && $1 == wait-online ]]; then 86 | network_wait_online 87 | elif [[ $# -eq 2 && $1 == @(start|stop) ]]; then 88 | # Expose the command 89 | Command=$1 90 | load_profile "$2" 91 | "network_$1" 92 | else 93 | exit_error "Usage: $0 {start|stop|wait-online} [profile]" 94 | fi 95 | 96 | 97 | # vim: ft=sh ts=4 et sw=4: 98 | -------------------------------------------------------------------------------- /src/lib/rfkill: -------------------------------------------------------------------------------- 1 | ## /usr/lib/netctl/globals needs to be sourced before this file 2 | 3 | 4 | ## Determine the system interface of an rfkill device 5 | # $1: interface name 6 | # $2: rfkill name 7 | rf_get_path() { 8 | local interface=$1 rfkill_name=${2:-auto} path 9 | 10 | if [[ $rfkill_name == "auto" ]]; then 11 | path=$(find -L "/sys/class/net/$interface/" -maxdepth 2 -type d -name "rfkill*" 2> /dev/null | head -n 1) 12 | if [[ $path ]]; then 13 | echo "$path" 14 | return 0 15 | fi 16 | report_error "No rfkill switch available on interface '$interface'" 17 | else 18 | for path in /sys/class/rfkill/*; do 19 | if [[ $(< "$path/name") == "$rfkill_name" ]]; then 20 | echo "$path" 21 | return 0 22 | fi 23 | done 24 | report_error "No rfkill switch with name '$rfkill_name'" 25 | fi 26 | return 1 27 | } 28 | 29 | ## Determine the blocking status of an rfkill device 30 | # $1: interface name 31 | # $2: rfkill name 32 | rf_status() { 33 | local path 34 | path=$(rf_get_path "$@") || return 1 35 | 36 | if (( $(< "$path/hard" ) )); then 37 | echo "hard" 38 | elif (( $(< "$path/soft" ) )); then 39 | echo "soft" 40 | fi 41 | } 42 | 43 | ## Set the soft blocking status of an rfkill device 44 | # $1: blocking status 45 | # $2: interface name 46 | # $3: rfkill name 47 | rf_set() { 48 | local block=$1 path 49 | shift 50 | path=$(rf_get_path "$@") || return 1 51 | 52 | report_debug "${FUNCNAME[1]}: echo '$block' > '$path/soft'" 53 | echo "$block" > "$path/soft" 54 | timeout_wait 1 '(( $(< "$path/soft") == block ))' 55 | } 56 | 57 | ## Block transmission through a wireless device 58 | # $1: interface name 59 | # $2: rfkill name 60 | rf_disable() { 61 | rf_set 1 "$@" 62 | } 63 | 64 | ## Unblock transmission through a wireless device 65 | # $1: interface name 66 | # $2: rfkill name 67 | rf_enable() { 68 | local status 69 | status=$(rf_status "$@") || return 1 70 | 71 | case $status in 72 | hard) 73 | report_error "Transmission is hard-blocked on interface '$interface'" 74 | return 1 75 | ;; 76 | soft) 77 | rf_set 0 "$@" 78 | ;; 79 | esac 80 | } 81 | 82 | 83 | # vim: ft=sh ts=4 et sw=4: 84 | -------------------------------------------------------------------------------- /src/lib/wpa: -------------------------------------------------------------------------------- 1 | ## /usr/lib/netctl/globals needs to be sourced before this file 2 | 3 | 4 | ## Wrapper around wpa_cli to deal with supplicant configurations that set a 5 | ## non-standard control path 6 | # $1: interface name 7 | # $2...: call to the supplicant 8 | wpa_call() { 9 | local args=( "-i" "$1" ) 10 | shift 11 | 12 | if [[ $WPA_CTRL_DIR ]]; then 13 | args+=("-p" "$WPA_CTRL_DIR") 14 | elif [[ $WPAConfigFile ]] && grep -q '^[[:space:]]*ctrl_interface=' "$WPAConfigFile"; then 15 | WPA_CTRL_DIR=$(sed -n '0,/^[[:space:]]*ctrl_interface=/s///p' "$WPAConfigFile") 16 | if [[ $WPA_CTRL_DIR == DIR=* ]]; then 17 | WPA_CTRL_DIR=${WPA_CTRL_DIR:4} 18 | WPA_CTRL_DIR=${WPA_CTRL_DIR%% GROUP=*} 19 | fi 20 | args+=( "-p" "$WPA_CTRL_DIR" ) 21 | fi 22 | do_debug wpa_cli "${args[@]}" "$@" 23 | } 24 | 25 | ## Check if an instance of the WPA supplicant is active on an interface 26 | # $1: interface name 27 | wpa_is_active() { 28 | [[ $(wpa_call "$1" ping 2> /dev/null) == "PONG" ]] 29 | } 30 | 31 | ## Retrieve the state of an instance of the WPA supplicant 32 | ## Displays one of: DISCONNECTED, INTERFACE_DISABLED, INACTIVE, SCANNING, 33 | ## AUTHENTICATING, ASSOCIATING, ASSOCIATED, 4WAY_HANDSHAKE, 34 | ## GROUP_HANDSHAKE, COMPLETED 35 | # $1: interface name 36 | wpa_get_state() { 37 | local state 38 | state=$(wpa_call "$1" status | grep -m1 '^wpa_state=') || return 1 39 | echo "${state#wpa_state=}" 40 | } 41 | 42 | ## Wait until the WPA supplicant reaches a listed state 43 | # $1: timeout 44 | # $2: interface name 45 | # $3...: accepted states 46 | wpa_wait_until_state() { 47 | local timeout=$1 interface=$2 states=( "${@:3}" ) 48 | timeout_wait "$timeout" \ 49 | 'in_array "$(wpa_get_state "$interface")" "${states[@]}"' 50 | } 51 | 52 | ## Wait while the WPA supplicant is in a listed state 53 | # $1: timeout 54 | # $2: interface name 55 | # $3...: rejected states 56 | wpa_wait_while_state() { 57 | local timeout=$1 interface=$2 states=( "${@:3}" ) 58 | timeout_wait "$timeout" \ 59 | '! in_array "$(wpa_get_state "$interface")" "${states[@]}"' 60 | } 61 | 62 | ## Wait for the WPA supplicant to finish association and authentication 63 | # $1: timeout 64 | # $2: interface name 65 | # $3...: additional accepted states 66 | wpa_wait_until_completed() { 67 | local timeout=$1 interface=$2 68 | shift 2 69 | if ! wpa_wait_until_state "$timeout" "$interface" "COMPLETED" "$@"; then 70 | report_error "WPA association/authentication failed for interface '$interface'" 71 | report_debug "WPA state for interface '$interface': $(wpa_get_state "$interface")" 72 | return 1 73 | fi 74 | } 75 | 76 | ## Start an instance of the WPA supplicant 77 | # $1: interface name 78 | # $2: interface driver(s) 79 | # $3: configuration file 80 | wpa_start() { 81 | local interface=$1 driver=$2 configuration 82 | local pidfile="/run/wpa_supplicant-$interface.pid" 83 | if [[ $3 ]]; then 84 | configuration="-c$3" 85 | else 86 | WPA_CTRL_DIR="/run/wpa_supplicant" 87 | configuration="-C$WPA_CTRL_DIR" 88 | fi 89 | 90 | if ! type wpa_supplicant &> /dev/null; then 91 | report_error "You need to install 'wpa_supplicant'" 92 | return 127 93 | fi 94 | 95 | do_debug wpa_supplicant -q -B -P "$pidfile" -i "$interface" -D "$driver" \ 96 | "$configuration" $WPAOptions >&2 97 | 98 | # Wait up to one second for the pid file to appear 99 | timeout_wait 1 '[[ -f $pidfile ]]' 100 | } 101 | 102 | ## Stop an instance of the WPA supplicant 103 | # $1: interface name 104 | wpa_stop() { 105 | local interface=$1 pidfile="/run/wpa_supplicant-$1.pid" 106 | # We need this as long as wpa_cli has a different default than netctl 107 | if [[ -z $WPA_CTRL_DIR && -z $WPAConfigFile ]]; then 108 | WPA_CTRL_DIR="/run/wpa_supplicant" 109 | fi 110 | 111 | # Done if wpa_supplicant is already terminated for this interface 112 | [[ -z $WPA_CTRL_DIR || -e "$WPA_CTRL_DIR/$interface" ]] || return 0 113 | 114 | wpa_call "$interface" terminate > /dev/null 115 | # Wait up to one second for the pid file to be removed 116 | if ! timeout_wait 1 '[[ ! -f $pidfile ]]'; then 117 | kill "$(< "$pidfile")" &> /dev/null 118 | fi 119 | } 120 | 121 | ## Scan for networks within range 122 | # $1: interface name 123 | # $2: fields of the wpa_supplicant scan_results 124 | # 1: bssid 2: frequency 3: signal level 4: flags 5: ssid 125 | wpa_supplicant_scan() { 126 | local interface=$1 fields=$2 spawned_wpa=no essids 127 | # temp file used, as keeping ESSID's with spaces in their name in arrays 128 | # is hard, obscure and kinda nasty. This is simpler and clearer. 129 | 130 | [[ $interface ]] || return 1 131 | essids=$(mktemp --tmpdir essid.XXXXXXXX) 132 | 133 | if ! wpa_is_active "$interface"; then 134 | wpa_start "$interface" "${WPADriver:-nl80211,wext}" || return 1 135 | spawned_wpa=yes 136 | fi 137 | 138 | wpa_call "$interface" scan > /dev/null 139 | # Wait at least 3 seconds for scan results 140 | sleep 3 141 | # Sometimes, that is not enough 142 | wpa_wait_while_state 7 "$interface" "SCANNING" 143 | wpa_call "$interface" scan_results | 144 | tail -n+2 | # Remove extraneous output 145 | sort -rn -k3 | # Sort by signal strength 146 | sort -u -k5 | # Remove duplicates 147 | sort -rn -k3 | # Re-sort as the removal disorders the list 148 | cut -f"$fields" > "$essids" 149 | 150 | if is_yes "$spawned_wpa"; then 151 | wpa_stop "$interface" 152 | fi 153 | 154 | # File of 0 length: no ssid's 155 | if [[ ! -s $essids ]]; then 156 | rm -f "$essids" 157 | return 1 158 | fi 159 | 160 | echo "$essids" 161 | } 162 | 163 | ## Print a string within quotes, unless it starts with the "-modifier 164 | ## Quoted: string "string" '""string"' 165 | ## Non-quoted: \"string "\"string" '"string' 166 | # $1: string 167 | wpa_quote() { 168 | local string=$1 169 | if [[ $string == \"* ]]; then 170 | printf '%s' "${string:1}" 171 | else 172 | printf '"%s"' "$string" 173 | fi 174 | } 175 | 176 | ## Unquote a string returned by wpa_call 177 | ## Possible representations of string: "string" 737472696e67 string 178 | # $1: string 179 | wpa_unquote() { 180 | local string="$1" 181 | if [[ $string == \"*\" ]]; then 182 | printf '%s' "${string:1:-1}" 183 | elif [[ $string == +([[:xdigit:]][[:xdigit:]]) ]]; then 184 | while [[ $string ]]; do 185 | printf "\\x${string:0:2}" 186 | string=${string:2} 187 | done 188 | else 189 | printf '%s' "${string}" 190 | fi 191 | } 192 | 193 | ## Create a configuration file for wpa_supplicant without any network blocks 194 | # $1: interface name 195 | wpa_make_config_file() { 196 | local config_file="$STATE_DIR/wpa_supplicant-$1.conf" 197 | 198 | if [[ -e $config_file ]]; then 199 | report_debug "The anticipated filename '$config_file' is not available" 200 | return 1 201 | fi 202 | mkdir -p "$STATE_DIR" /run/wpa_supplicant 203 | if ! : > "$config_file"; then 204 | report_debug "Could not create the configuration file '$config_file'" 205 | return 1 206 | fi 207 | 208 | echo "ctrl_interface=/run/wpa_supplicant" >> "$config_file" 209 | echo "ctrl_interface_group=${WPAGroup:-wheel}" >> "$config_file" 210 | [[ $Country ]] && echo "country=$Country" >> "$config_file" 211 | if is_yes "${AdHoc:-no}"; then 212 | echo "ap_scan=2" >> "$config_file" 213 | fi 214 | echo "$config_file" 215 | } 216 | 217 | ## Generate a network block for wpa_supplicant 218 | # $Security: type of wireless security 219 | wpa_make_config_block() { 220 | case $Security in 221 | none) 222 | echo "key_mgmt=NONE" 223 | ;; 224 | wep) 225 | echo "key_mgmt=NONE" 226 | echo "wep_tx_keyidx=0" 227 | if [[ $Key == +([[:xdigit:]][[:xdigit:]]) ]]; then 228 | echo "wep_key0=$Key" 229 | else 230 | echo "wep_key0=$(wpa_quote "$Key")" 231 | fi 232 | ;; 233 | wpa) 234 | echo "key_mgmt=WPA-PSK SAE" 235 | echo "ieee80211w=1" 236 | if [[ "${#Key}" -eq 64 && $Key == +([[:xdigit:]]) ]]; then 237 | echo "psk=$Key" 238 | else 239 | echo "psk=$(wpa_quote "$Key")" 240 | fi 241 | ;; 242 | wpa-configsection) 243 | printf '%s\n' "${WPAConfigSection[@]}" 244 | return 245 | ;; 246 | *) 247 | report_error "Unsupported security setting: '$Security'" 248 | return 1 249 | ;; 250 | esac 251 | 252 | echo "ssid=$(wpa_quote "$ESSID")" 253 | [[ $AP ]] && echo "bssid=${AP,,}" 254 | is_yes "${Hidden:-no}" && echo "scan_ssid=1" 255 | is_yes "${AdHoc:-no}" && echo "mode=1" 256 | [[ $ScanFrequencies ]] && echo "scan_freq=$ScanFrequencies" 257 | [[ $Frequency ]] && echo "frequency=$Frequency" 258 | [[ $Priority ]] && echo "priority=$Priority" 259 | } 260 | 261 | ## Remove a configuration file for wpa_supplicant 262 | # $1: interface name 263 | wpa_destroy_config_file() { 264 | local config_file="$STATE_DIR/wpa_supplicant-$1.conf" 265 | if [[ -f $config_file && -O $config_file ]]; then 266 | do_debug rm -f "$config_file" 267 | fi 268 | } 269 | 270 | 271 | # vim: ft=sh ts=4 et sw=4: 272 | -------------------------------------------------------------------------------- /src/netctl-auto: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # Contributed by: Sebastian Wicki 3 | 4 | . /usr/lib/netctl/globals 5 | . "$SUBR_DIR/interface" 6 | . "$SUBR_DIR/rfkill" 7 | . "$SUBR_DIR/wpa" 8 | 9 | : ${ACTION_SCRIPT:=$SUBR_DIR/auto.action} 10 | 11 | 12 | usage() { 13 | cat << END 14 | Usage: netctl-auto {COMMAND} ... 15 | [--help|--version] 16 | 17 | Commands: 18 | list List available profiles (active='*', disabled='!') 19 | switch-to [PROFILE] Switch to a profile, enable it if necessary 20 | is-active [PROFILE] Check whether a profile is active 21 | enable [PROFILE] Enable a profile for automatic selection 22 | disable [PROFILE] Disable a profile for automatic selection 23 | enable-all Enable all profiles for automatic selection 24 | disable-all Disable all profiles for automatic selection 25 | is-enabled [PROFILE] Check whether a profile is enabled 26 | END 27 | } 28 | 29 | ## Print a list of interfaces for which netctl-auto is active 30 | list_netctl_auto_interfaces() { 31 | systemctl --full --no-legend --no-pager --plain --state=running \ 32 | list-units 'netctl-auto@*.service' | while read -r name _; do 33 | systemd-escape --unescape --instance "$name" 34 | done 35 | } 36 | 37 | ## List all profiles available to the WPA supplicant 38 | ## Output format: INTERFACE ID FLAG PROFILE.. 39 | ## INTERFACE network interface of the profile 40 | ## ID wpa_supplicant numerical network id 41 | ## FLAG 'e'=enabled, 'd'=disabled, 'a'=active 42 | ## PROFILE.. profile name, may contain spaces 43 | list_wpa_profiles() { 44 | local interface 45 | for interface in $(list_netctl_auto_interfaces); do 46 | local id ssid bssid flags 47 | while IFS=$'\t' read -r id ssid bssid flags; do 48 | local flag="e" 49 | if [[ "$flags" =~ \[CURRENT\] ]]; then 50 | flag="a" 51 | elif [[ "$flags" =~ \[DISABLED\] ]]; then 52 | flag="d" 53 | fi 54 | 55 | local profile=$(wpa_call "$interface" get_network "$id" id_str) 56 | profile=$(wpa_unquote "$profile") 57 | 58 | echo "$interface" "$id" "$flag" "$profile" 59 | done < <(wpa_call "$interface" list_networks | tail -n+2) 60 | done 61 | } 62 | 63 | ## Get the WPA supplicant network id and interface for the given profile 64 | ## Output format: INTERFACE ID 65 | # $1: profile name 66 | get_wpa_network_id() { 67 | local interface id flag profile 68 | while read -r interface id flag profile; do 69 | if [[ $profile == "$1" ]]; then 70 | echo "$interface" "$id" 71 | return 0 72 | fi 73 | done < <(list_wpa_profiles) 74 | 75 | report_error "Profile '$1' does not exist or is not available" 76 | return 1 77 | } 78 | 79 | ## Enable or disable profiles in the WPA supplicant 80 | # $1: profile action: "enable", "disable", "enable-all" or "disable-all" 81 | # $2: profile name if action is "enable" or "disable" 82 | profile_enable_disable() { 83 | local action="$1" profile="$2" 84 | local id interfaces wpa_cmd 85 | 86 | if [[ $profile ]]; then 87 | read -r interfaces id < <(get_wpa_network_id "$profile") || return 1 88 | else 89 | interfaces=$(list_netctl_auto_interfaces) 90 | fi 91 | 92 | case $action in 93 | enable) 94 | wpa_cmd=(enable_network "$id");; 95 | disable) 96 | wpa_cmd=(disable_network "$id");; 97 | enable-all) 98 | wpa_cmd=(enable_network all);; 99 | disable-all) 100 | wpa_cmd=(disable_network all);; 101 | *) 102 | return 1; 103 | esac 104 | 105 | local interface 106 | for interface in $interfaces; do 107 | wpa_call "$interface" "${wpa_cmd[@]}" >/dev/null 108 | if [[ "${wpa_cmd[0]}" == "enable_network" ]]; then 109 | wpa_call "$interface" reassociate >/dev/null 110 | fi 111 | done 112 | } 113 | 114 | ## Select profile in WPA supplicant, but preserve state of all other networks 115 | # $1: profile name 116 | switch_to() { 117 | local profile="$1" 118 | local id interface timeout 119 | 120 | # Load profile interface, WPA network id and timeout 121 | read -r interface id < <(get_wpa_network_id "$profile") || return 1 122 | timeout=$(. "$PROFILE_DIR/$profile" >/dev/null; echo ${TimeoutWPA:=15}) 123 | 124 | # List of enabled networks 125 | local enabled_networks=$(wpa_call "$interface" list_networks | tail -n+2 | \ 126 | cut -f 1,4 | grep -Fv '[DISABLED]' | cut -f 1 | tr '\n' ' ') 127 | 128 | reenable_networks() { 129 | for network in $enabled_networks; do 130 | wpa_call "$interface" enable_network "$network" >/dev/null 131 | done 132 | 133 | if [[ $(wpa_get_state "$interface") != "COMPLETED" ]]; then 134 | if ! in_array "$id" $enabled_networks; then 135 | wpa_call "$interface" disable_network "$id" >/dev/null 136 | fi 137 | fi 138 | } 139 | 140 | # Reenable networks in case user aborts 141 | trap "reenable_networks; exit 1" SIGINT SIGTERM 142 | 143 | # select_network will disable all other networks on that interface 144 | wpa_call "$interface" select_network "$id" >/dev/null 145 | wpa_wait_until_completed "$timeout" "$interface" 146 | 147 | reenable_networks 148 | } 149 | 150 | ## Check whether a profile is active 151 | # $1: profile name 152 | is_active() { 153 | local interface id flag profile 154 | while read -r interface id flag profile; do 155 | if [[ $profile == "$1" ]]; then 156 | if [[ $flag == "a" ]]; then 157 | echo "active" 158 | return 0 159 | else 160 | echo "inactive" 161 | return 1 162 | fi 163 | fi 164 | done < <(list_wpa_profiles) 165 | echo "unknown profile: '$1'" 166 | return 1 167 | } 168 | 169 | ## Check whether a profile is enabled 170 | # $1: profile name 171 | is_enabled() { 172 | local interface id flag profile 173 | while read -r interface id flag profile; do 174 | if [[ $profile == "$1" ]]; then 175 | if [[ $flag != "d" ]]; then 176 | echo "enabled" 177 | return 0 178 | else 179 | echo "disabled" 180 | return 1 181 | fi 182 | fi 183 | done < <(list_wpa_profiles) 184 | echo "unknown profile: '$1'" 185 | return 1 186 | } 187 | 188 | ## List all available profiles and their status 189 | list() { 190 | local interface id flag profile 191 | list_wpa_profiles | while read -r interface id flag profile; do 192 | echo "$(echo $flag | tr 'aed' '* !')" "$profile" 193 | done 194 | } 195 | 196 | ## Start and generate config file for the WPA supplicant, monitor for changes 197 | # $1: interface 198 | start() { 199 | local interface="$1" 200 | 201 | if interface_is_up "$interface"; then 202 | exit_error "The interface '$interface' is already up" 203 | fi 204 | if [[ $RFKill ]]; then 205 | rf_enable "$interface" "$RFKill" || return 1 206 | fi 207 | 208 | if ! WPAConfigFile=$(wpa_make_config_file "$interface"); then 209 | exit_error "Could not create the configuration file for interface '$interface'" 210 | fi 211 | # Disable p2p to prevent wpa_supplicant from creating another control interface 212 | echo "p2p_disabled=1" >> "$WPAConfigFile" 213 | 214 | filter_profiles "$interface" wireless | while IFS= read -r profile; do 215 | report_debug "Examining profile '$profile'" 216 | ( 217 | load_profile "$profile" 218 | is_yes "${ExcludeAuto:-no}" && exit 219 | # Set default and exclude wpa-config as it does not fit this scheme 220 | [[ ${Security:=none} != "wpa-config" ]] || exit 221 | printf '%s\n' "network={" "$(wpa_make_config_block)" "id_str=\"$profile\"" "}" >> "$WPAConfigFile" 222 | report_notice "Included profile '$profile'" 223 | ) 224 | done 225 | 226 | # Start the WPA supplicant and wpa_cli 227 | : ${WPADriver:=nl80211,wext} 228 | WPAOptions+=" -W" 229 | if wpa_start "$interface" "$WPADriver" "$WPAConfigFile"; then 230 | if wpa_call "$interface" -B -a "$ACTION_SCRIPT"; then 231 | return 0 232 | fi 233 | wpa_stop "$interface" 234 | bring_interface_down "$interface" 235 | fi 236 | # Systemd executes cleanup on failure 237 | return 1 238 | } 239 | 240 | ## Stop the WPA supplicant, which automatically stops wpa_cli 241 | # $1: interface 242 | stop() { 243 | local interface="$1" 244 | 245 | wpa_stop "$interface" 246 | bring_interface_down "$interface" 247 | if [[ $RFKill ]]; then 248 | rf_disable "$interface" "$RFKill" 249 | fi 250 | } 251 | 252 | ## Remove WPA supplicant configuration files 253 | # $1: interface 254 | clean() { 255 | wpa_destroy_config_file "$1" 256 | } 257 | 258 | 259 | case $# in 260 | 1) 261 | case $1 in 262 | --version) 263 | report_notice "netctl version $NETCTL_VERSION";; 264 | --help) 265 | usage;; 266 | list) 267 | "$1";; 268 | enable-all|disable-all) 269 | profile_enable_disable "$1";; 270 | *) 271 | exit_error "$(usage)";; 272 | esac;; 273 | 2) 274 | case $1 in 275 | enable|disable) 276 | profile_enable_disable "$1" "$2";; 277 | switch-to|is-active|is-enabled) 278 | "${1//-/_}" "$2";; 279 | start|stop|clean) 280 | if [[ -t 0 ]]; then 281 | exit_error "Use 'systemctl ${1/clean/stop} netctl-auto@$2' to $1 netctl-auto." 282 | fi 283 | ensure_root "$(basename "$0")" 284 | load_interface_config "$2" 285 | "$1" "$2";; 286 | *) 287 | exit_error "$(usage)";; 288 | esac;; 289 | *) 290 | exit_error "$(usage)";; 291 | esac 292 | 293 | 294 | # vim: ft=sh ts=4 et sw=4: 295 | -------------------------------------------------------------------------------- /src/netctl.in: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | . /usr/lib/netctl/globals 4 | 5 | 6 | usage() { 7 | cat << END 8 | Usage: netctl {COMMAND} [PROFILE] 9 | [--help|--version] 10 | 11 | Commands: 12 | list List available profiles 13 | store Save which profiles are active 14 | restore Load saved profiles 15 | stop-all Stops all profiles 16 | start [PROFILE] Start a profile 17 | stop [PROFILE] Stop a profile 18 | restart [PROFILE] Restart a profile 19 | switch-to [PROFILE] Switch to a profile 20 | is-active [PROFILE] Check whether a profile is active 21 | status [PROFILE] Show runtime status of a profile 22 | enable [PROFILE] Enable the systemd unit for a profile 23 | disable [PROFILE] Disable the systemd unit for a profile 24 | reenable [PROFILE] Reenable the systemd unit for a profile 25 | is-enabled [PROFILE] Check whether a profile is enabled 26 | edit [PROFILE] Edit a profile file 27 | verify [PROFILE] Check the syntax of a profile file 28 | wait-online [PROFILE] Wait for a profile to finish connecting 29 | END 30 | } 31 | 32 | list() { 33 | local indicators=( ' ' '+' '*' ) i 34 | list_profiles | while IFS= read -r Profile; do 35 | if sd_call "is-active --quiet" "$Profile" &> /dev/null; then 36 | [[ $(sd_status_text "$Profile") == "online" ]] 37 | (( i = 2 - $? )) 38 | else 39 | (( i = 0 )) 40 | fi 41 | printf '%s %s\n' "${indicators[i]}" "$Profile" 42 | done 43 | } 44 | 45 | store() { 46 | mkdir -p "$(dirname "$STATE_FILE")" 47 | list_profiles | while IFS= read -r Profile; do 48 | if sd_call "is-active --quiet" "$Profile" &> /dev/null; then 49 | printf '%s\n' "$Profile" 50 | fi 51 | done > "$STATE_FILE" 52 | } 53 | 54 | restore() { 55 | if [[ ! -r $STATE_FILE ]]; then 56 | exit_error "Could not read state file '$STATE_FILE'" 57 | elif [[ ! -s $STATE_FILE ]]; then 58 | report_debug "No profiles to restore in state file '$STATE_FILE'" 59 | else 60 | mapfile -t Profiles < "$STATE_FILE" 61 | do_debug sd_call start "${Profiles[@]}" 62 | fi 63 | } 64 | 65 | stop_all() { 66 | # We cannot pipe to mapfile, as the end of a pipe is inside a subshell 67 | mapfile -t Profiles < <(list_profiles) 68 | if (( ${#Profiles[@]} )); then 69 | do_debug sd_call stop "${Profiles[@]}" 2> >(grep -Fv 'not loaded' >&2) 70 | fi 71 | } 72 | 73 | switch_to() { 74 | Interface=$(. "$PROFILE_DIR/$1" >/dev/null; printf '%s' "$Interface") 75 | if [[ -z $Interface ]]; then 76 | exit_error "Profile '$1' does not specify an interface" 77 | fi 78 | mapfile -t Profiles < <(filter_profiles "$Interface") 79 | if (( ${#Profiles[@]} )); then 80 | do_debug sd_call stop "${Profiles[@]}" 2> >(grep -Fv 'not loaded' >&2) 81 | fi 82 | do_debug sd_call start "$1" 83 | } 84 | 85 | unit_enable() { 86 | local unit=$(systemd-escape --template=netctl@.service "$1") target 87 | load_profile "$1" 88 | 89 | target="@systemdsystemconfdir@/multi-user.target.wants/$unit" 90 | if [[ -e $target ]]; then 91 | report_error "The profile '$1' is already enabled" 92 | return 1 93 | fi 94 | do_readable mkdir -p "$(dirname "$target")" 95 | ln -vs "@systemdsystemunitdir@/netctl@.service" "$target" 96 | 97 | target="@systemdsystemconfdir@/$unit.d/profile.conf" 98 | do_readable mkdir -p "$(dirname "$target")" 99 | do_readable touch "$target" 100 | echo "[Unit]" > "$target" 101 | if [[ $Description ]]; then 102 | echo "Description=$Description" >> "$target" 103 | fi 104 | declare -p BindsToInterfaces &> /dev/null || BindsToInterfaces=$Interface 105 | if (( ${#BindsToInterfaces[@]} )); then 106 | : ${InterfaceRoot=sys/subsystem/net/devices/} 107 | printf "BindsTo=$(systemd-escape "$InterfaceRoot")%s.device\n" \ 108 | $(systemd-escape "${BindsToInterfaces[@]}") >> "$target" 109 | printf "After=$(systemd-escape "$InterfaceRoot")%s.device\n" \ 110 | $(systemd-escape "${BindsToInterfaces[@]}") >> "$target" 111 | fi 112 | if (( ${#After[@]} )); then 113 | printf 'After=netctl@%s.service\n' \ 114 | $(systemd-escape "${After[@]}") >> "$target" 115 | fi 116 | report_notice "generated '$target'" 117 | } 118 | 119 | unit_disable() { 120 | local unit=$(systemd-escape --template=netctl@.service "$1") 121 | rm -vfd "@systemdsystemconfdir@"{/multi-user.target.wants,}"/$unit" \ 122 | "@systemdsystemconfdir@/$unit.d"{/profile.conf,} 123 | } 124 | 125 | unit_reenable() { 126 | unit_disable "$1" 127 | unit_enable "$1" 128 | } 129 | 130 | wait_online() { 131 | local profile="$1" 132 | if ! timeout_wait "${TIMEOUT_ONLINE:-120}" \ 133 | '! sd_call "is-active --quiet" "$profile" || \ 134 | [[ $(sd_status_text "$profile") == "online" ]]'; then 135 | report_notice "timeout" 136 | return 1 137 | elif ! sd_call "is-active --quiet" "$profile"; then 138 | report_notice "failed" 139 | return 1 140 | fi 141 | } 142 | 143 | 144 | case $# in 145 | 1) 146 | case $1 in 147 | --version) 148 | report_notice "netctl version $NETCTL_VERSION";; 149 | --help) 150 | usage;; 151 | list) 152 | list;; 153 | store|restore) 154 | ensure_root "$(basename "$0")" 155 | "$1";; 156 | stop-all) 157 | stop_all;; 158 | *) 159 | exit_error "$(usage)";; 160 | esac;; 161 | 2) 162 | case $1 in 163 | start|stop|restart|is-active|status|is-enabled) 164 | sd_call "$1" "$2";; 165 | switch-to) 166 | ensure_root "$(basename "$0")" 167 | verify_profile "$2" 168 | switch_to "$2";; 169 | enable|disable|reenable) 170 | ensure_root "$(basename "$0")" 171 | if [[ $1 != "disable" ]]; then 172 | verify_profile "$2" 173 | fi 174 | "unit_$1" "$2" 175 | if systemd-notify --booted; then 176 | systemctl daemon-reload 177 | fi;; 178 | edit) 179 | exec ${EDITOR:-nano} "$PROFILE_DIR/$2";; 180 | verify) 181 | verify_profile "$2";; 182 | wait-online) 183 | wait_online "$2";; 184 | *) 185 | exit_error "$(usage)";; 186 | esac;; 187 | *) 188 | exit_error "$(usage)";; 189 | esac 190 | 191 | 192 | # vim: ft=sh ts=4 et sw=4: 193 | -------------------------------------------------------------------------------- /src/wifi-menu: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | . /usr/lib/netctl/globals 4 | . "$SUBR_DIR/interface" 5 | . "$SUBR_DIR/rfkill" 6 | . "$SUBR_DIR/wpa" 7 | 8 | 9 | usage() { 10 | cat << END 11 | Usage: wifi-menu [-h | --help] [-o | --obscure] [INTERFACE] 12 | 13 | Interactively connect to a wireless network on INTERFACE using netctl. 14 | If only one wireless interface is available, INTERFACE can be omitted. 15 | 16 | Arguments: 17 | -h, --help Show this help 18 | -o, --obscure Show asterisks for the characters of the password 19 | and store the password as a hexadecimal string 20 | END 21 | } 22 | 23 | # Undo printf escaping in $1 24 | printf_decode() { 25 | printf -- "${1//%/%%}" 26 | } 27 | 28 | # Prepare $1 for use in a special quoting context 29 | quote_safe() { 30 | if [[ "$1" = \"* ]]; then 31 | printf '""%s"' "$1" 32 | else 33 | printf '%s' "$1" 34 | fi 35 | } 36 | 37 | # Fill PROFILES and ESSIDS with the profile names and essids and fill GENERATED 38 | # with the names of automatically generated profiles for interface $1 39 | init_profiles() { 40 | local i=0 essid profile 41 | while IFS= read -r profile; do 42 | # Sandbox the sourcing of profiles 43 | essid=$( 44 | source "$PROFILE_DIR/$profile" > /dev/null 45 | if [[ "$Interface" = "$1" && -n "$ESSID" ]]; then 46 | if [[ "$ESSID" = \"\"*\" ]]; then 47 | ESSID=${ESSID:2:-1} 48 | fi 49 | printf '%s' "$ESSID" 50 | if [[ "$Description" =~ "Automatically generated" ]]; then 51 | return 2 52 | else 53 | return 1 54 | fi 55 | fi 56 | return 0 57 | ) 58 | case $? in 59 | 2) 60 | GENERATED+=("$profile") 61 | ;& 62 | 1) 63 | PROFILES[i]=$profile 64 | ESSIDS[i]=$essid 65 | (( ++i )) 66 | ;; 67 | esac 68 | done < <(list_profiles) 69 | } 70 | 71 | # Build ENTRIES as an argument list for dialog based on scan results in $1 72 | init_entries() { 73 | local i=0 sep=$'\t' decoded flags signal ssid 74 | while IFS=$'\t' read -r signal flags ssid; do 75 | decoded=$(printf_decode "$ssid") 76 | ENTRIES[i++]="--" # the SSID might look like an option to dialog 77 | if [[ "$CHARMAP" = "UTF-8" ]]; then 78 | ENTRIES[i++]=$decoded 79 | else 80 | ENTRIES[i++]=$ssid 81 | fi 82 | if is_yes "${CONNECTED:-no}" && [[ "$decoded" = "$CONNECTION" ]]; then 83 | ENTRIES[i]="*" # Currently connected 84 | elif in_array "$decoded" "${ESSIDS[@]}"; then 85 | if in_array "$(ssid_to_profile "$decoded")" "${GENERATED[@]}"; then 86 | ENTRIES[i]="." # Automatically generated 87 | else 88 | ENTRIES[i]=":" # Handmade 89 | fi 90 | else 91 | ENTRIES[i]=" " # Not present 92 | fi 93 | if [[ "$flags" =~ WPA3|WPA2|WPA|WEP ]]; then 94 | ENTRIES[i]+="${sep}${BASH_REMATCH[0],,}" 95 | else 96 | ENTRIES[i]+="${sep}none" 97 | fi 98 | ENTRIES[i]+=" ${sep}${signal}" 99 | (( ++i )) 100 | done < "$1" 101 | } 102 | 103 | # Find a profile name for ssid $1 104 | ssid_to_profile() { 105 | local i 106 | for i in $(seq 0 $((${#ESSIDS[@]}-1))); do 107 | if [[ "$1" = "${ESSIDS[i]}" ]]; then 108 | printf '%s' "${PROFILES[i]}" 109 | return 0 110 | fi 111 | done 112 | return 1 113 | } 114 | 115 | # Ask the user for the name of the new profile 116 | confirm_profile() { 117 | local msg="Enter a name for the new profile\n" 118 | PROFILE=$(dialog --inputbox "$msg" 10 50 "$PROFILE" --stdout) || return $? 119 | if [[ "$PROFILE" = */* ]]; then 120 | PROFILE=${PROFILE//\//_} 121 | confirm_profile 122 | elif [[ -e "$PROFILE_DIR/$PROFILE" ]]; then 123 | msg="A profile by the name '$PROFILE' already exists. 124 | Do you want to overwrite it?" 125 | dialog --yesno "$msg" 10 50 --stdout || confirm_profile 126 | fi 127 | } 128 | 129 | # Create a profile for ssid $1 130 | create_profile() { 131 | local box flags key msg security signal ssid 132 | PROFILE=$(iconv -c -f UTF-8 -t //TRANSLIT <<< "$1") 133 | PROFILE="$INTERFACE-${PROFILE//[?\/]/_}" 134 | [[ -e "$PROFILE_DIR/$PROFILE" ]] && PROFILE+=".wifi-menu" 135 | confirm_profile || return $? 136 | while IFS=$'\t' read -r signal flags ssid; do 137 | [[ "$(printf_decode "$ssid")" != "$1" ]] || break 138 | done < "$NETWORKS" 139 | if [[ "$flags" =~ WPA|WEP ]]; then 140 | security=${BASH_REMATCH[0],,} 141 | else 142 | security=none 143 | fi 144 | if [[ "$flags" =~ PSK|SAE|WEP ]]; then 145 | if is_yes "${OBSCURE:-no}"; then 146 | box="--insecure --passwordbox" 147 | else 148 | box="--inputbox" 149 | fi 150 | msg="Enter $security security key for\n'$1'" 151 | key=$(dialog $box "$msg" 10 40 --stdout) || return $? 152 | if [[ "${BASH_REMATCH[0]}" = "WEP" ]]; then 153 | if [[ "$key" = +([[:xdigit:]][[:xdigit:]]) ]]; then 154 | key="\"$key" 155 | else 156 | key=$(quote_safe "$key") 157 | fi 158 | elif [[ ${#key} -ge 8 && ${#key} -le 63 ]]; then 159 | if is_yes "${OBSCURE:-no}"; then 160 | key="\"$(wpa_passphrase "$1" "$key" | sed -n 's/^[[:space:]]*psk=//p')" 161 | else 162 | key=$(quote_safe "$key") 163 | fi 164 | elif [[ ${#key} -eq 64 && "$key" = +([[:xdigit:]]) ]]; then 165 | key="\"$key" 166 | else 167 | return 4 168 | fi 169 | fi 170 | cat << EOF > "$PROFILE_DIR/$PROFILE" 171 | Description='Automatically generated profile by wifi-menu' 172 | Interface=$INTERFACE 173 | Connection=wireless 174 | Security=$security 175 | ESSID=$(printf '%q' "$(quote_safe "$1")") 176 | IP=dhcp 177 | ${key+Key=$(printf '%q' "$key")} 178 | EOF 179 | printf '%s' "$PROFILE" 180 | return 0 181 | } 182 | 183 | # Connect to ssid $1 using an available profile or an automatically created one 184 | # if none exists 185 | connect_to_ssid() { 186 | local msg 187 | PROFILE=$(ssid_to_profile "$1") 188 | if [[ $? -ne 0 ]]; then 189 | PROFILE=$(create_profile "$1") || return $? 190 | NEW_PROFILE=yes 191 | fi 192 | clear 193 | if systemctl is-active --quiet "netctl-auto@$INTERFACE.service"; then 194 | report_notice "Interface '$INTERFACE' is controlled by netctl-auto" 195 | if is_yes "${NEW_PROFILE:-no}"; then 196 | do_debug systemctl restart "netctl-auto@$INTERFACE.service" 197 | fi 198 | do_debug netctl-auto switch-to "$PROFILE" 199 | elif ! netctl switch-to "$PROFILE" || ! netctl wait-online "$PROFILE"; then 200 | if is_yes "${NEW_PROFILE:-no}"; then 201 | msg=" CONNECTING FAILED 202 | 203 | Do you want to keep the generated profile ('$PROFILE')?" 204 | dialog --yesno "$msg" 10 40 --stdout || rm "$PROFILE_DIR/$PROFILE" 205 | clear 206 | fi 207 | return 2 208 | fi 209 | return 0 210 | } 211 | 212 | 213 | while [[ "$1" = -* ]]; do 214 | case "$1" in 215 | -h|--help) 216 | usage 217 | exit 218 | ;; 219 | -o|--obscure) 220 | OBSCURE=yes 221 | shift 222 | ;; 223 | -*) 224 | report_error "Invalid option: $1" 225 | usage 226 | exit 255 227 | ;; 228 | esac 229 | done 230 | if [[ $# -gt 1 ]]; then 231 | report_error "Too many arguments" 232 | usage 233 | exit 255 234 | fi 235 | 236 | ensure_root "$(basename "$0")" 237 | if ! type dialog &> /dev/null; then 238 | exit_error "Please install 'dialog' to use wifi-menu" 239 | fi 240 | CHARMAP=$(locale charmap) 241 | cd / # We do not want to spawn anything that can block unmounting 242 | 243 | INTERFACE=$1 244 | if [[ -z "$INTERFACE" ]]; then 245 | INTERFACE=(/sys/class/net/*/wireless/) 246 | if [[ ${#INTERFACE[@]} -ne 1 || ! -d "$INTERFACE" ]]; then 247 | report_error "Invalid interface specification" 248 | usage 249 | exit 255 250 | fi 251 | INTERFACE=${INTERFACE:15:-10} 252 | report_debug "Using interface '$INTERFACE'" 253 | elif ! is_interface "$INTERFACE"; then 254 | exit_error "No such interface: $INTERFACE" 255 | fi 256 | load_interface_config "$INTERFACE" 257 | 258 | if [[ "$RFKill" && "$(rf_status "$INTERFACE" "$RFKill")" ]]; then 259 | if ! rf_enable "$INTERFACE" "$RFKill"; then 260 | exit_error "Could not unblock transmission on interface '$INTERFACE'" 261 | fi 262 | RF_UNBLOCKED=yes 263 | fi 264 | 265 | echo -n "Scanning for networks... " 266 | if CONNECTION=$(wpa_call "$INTERFACE" status 2> /dev/null | grep -m 1 '^ssid='); then 267 | CONNECTION=$(printf_decode "${CONNECTION#ssid=}") 268 | CONNECTED=yes 269 | fi 270 | NETWORKS=$(wpa_supplicant_scan "$INTERFACE" 3,4,5) 271 | RETURN=$? 272 | 273 | if is_yes "${RF_UNBLOCKED:-no}"; then 274 | rf_disable "$INTERFACE" "$RFKill" 275 | fi 276 | 277 | if (( RETURN == 0 )); then 278 | trap 'rm -f "$NETWORKS"' EXIT 279 | echo "done" 280 | init_profiles "$INTERFACE" 281 | init_entries "$NETWORKS" 282 | MSG="Select the network you wish to use 283 | Flags description: 284 | * - active connection present 285 | : - handmade profile present 286 | . - automatically generated profile present" 287 | CHOICE=$(dialog --menu "$MSG" 24 50 12 "${ENTRIES[@]}" --stdout) 288 | RETURN=$? 289 | if (( RETURN == 0 )); then 290 | if [[ "$CHARMAP" != "UTF-8" ]]; then 291 | CHOICE=$(printf_decode "$CHOICE") 292 | fi 293 | connect_to_ssid "$CHOICE" 294 | RETURN=$? 295 | fi 296 | else 297 | echo "failed" 298 | RETURN=3 299 | fi 300 | 301 | case $RETURN in 302 | 0|2) # Connected | Connecting failed 303 | ;; 304 | 1) # Canceled 305 | clear 306 | ;; 307 | 3) # No networks found 308 | report_error "No networks found" 309 | ;; 310 | 4) # Invalid passphrase length (WEP keys have tighter restrictions) 311 | clear 312 | report_error "Passphrase must be 8..63 characters" 313 | ;; 314 | 255) # ESC or error 315 | clear 316 | report_error "Aborted" 317 | ;; 318 | *) # Should not happen 319 | report_error "Unexpected return code from dialog: $RETURN" 320 | RETURN=7 321 | ;; 322 | esac 323 | exit $RETURN 324 | 325 | 326 | # vim: ft=sh ts=4 et sw=4: 327 | --------------------------------------------------------------------------------