diff --git a/openair3/NEMO_SHO/COPYING b/openair3/NEMO_SHO/COPYING
deleted file mode 100644
index 94a9ed024d3859793618152ea559a168bbcbb5e2..0000000000000000000000000000000000000000
--- a/openair3/NEMO_SHO/COPYING
+++ /dev/null
@@ -1,674 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc.
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
-
- The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works. By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users. We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors. You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
- To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights. Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received. You must make sure that they, too, receive
-or can get the source code. And you must show them these terms so they
-know their rights.
-
- Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
- For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software. For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
- Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so. This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software. The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable. Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products. If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
- Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary. To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- TERMS AND CONDITIONS
-
- 0. Definitions.
-
- "This License" refers to version 3 of the GNU General Public License.
-
- "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
- "The Program" refers to any copyrightable work licensed under this
-License. Each licensee is addressed as "you". "Licensees" and
-"recipients" may be individuals or organizations.
-
- To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy. The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
- A "covered work" means either the unmodified Program or a work based
-on the Program.
-
- To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy. Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
- To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies. Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
- An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License. If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
- 1. Source Code.
-
- The "source code" for a work means the preferred form of the work
-for making modifications to it. "Object code" means any non-source
-form of a work.
-
- A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
- The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form. A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
- The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities. However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work. For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
- The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
- The Corresponding Source for a work in source code form is that
-same work.
-
- 2. Basic Permissions.
-
- All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met. This License explicitly affirms your unlimited
-permission to run the unmodified Program. The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work. This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
- You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force. You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright. Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
- Conveying under any other circumstances is permitted solely under
-the conditions stated below. Sublicensing is not allowed; section 10
-makes it unnecessary.
-
- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
- No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
- When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
- 4. Conveying Verbatim Copies.
-
- You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
- You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
- 5. Conveying Modified Source Versions.
-
- You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
- a) The work must carry prominent notices stating that you modified
- it, and giving a relevant date.
-
- b) The work must carry prominent notices stating that it is
- released under this License and any conditions added under section
- 7. This requirement modifies the requirement in section 4 to
- "keep intact all notices".
-
- c) You must license the entire work, as a whole, under this
- License to anyone who comes into possession of a copy. This
- License will therefore apply, along with any applicable section 7
- additional terms, to the whole of the work, and all its parts,
- regardless of how they are packaged. This License gives no
- permission to license the work in any other way, but it does not
- invalidate such permission if you have separately received it.
-
- d) If the work has interactive user interfaces, each must display
- Appropriate Legal Notices; however, if the Program has interactive
- interfaces that do not display Appropriate Legal Notices, your
- work need not make them do so.
-
- A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit. Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
- 6. Conveying Non-Source Forms.
-
- You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
- a) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by the
- Corresponding Source fixed on a durable physical medium
- customarily used for software interchange.
-
- b) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by a
- written offer, valid for at least three years and valid for as
- long as you offer spare parts or customer support for that product
- model, to give anyone who possesses the object code either (1) a
- copy of the Corresponding Source for all the software in the
- product that is covered by this License, on a durable physical
- medium customarily used for software interchange, for a price no
- more than your reasonable cost of physically performing this
- conveying of source, or (2) access to copy the
- Corresponding Source from a network server at no charge.
-
- c) Convey individual copies of the object code with a copy of the
- written offer to provide the Corresponding Source. This
- alternative is allowed only occasionally and noncommercially, and
- only if you received the object code with such an offer, in accord
- with subsection 6b.
-
- d) Convey the object code by offering access from a designated
- place (gratis or for a charge), and offer equivalent access to the
- Corresponding Source in the same way through the same place at no
- further charge. You need not require recipients to copy the
- Corresponding Source along with the object code. If the place to
- copy the object code is a network server, the Corresponding Source
- may be on a different server (operated by you or a third party)
- that supports equivalent copying facilities, provided you maintain
- clear directions next to the object code saying where to find the
- Corresponding Source. Regardless of what server hosts the
- Corresponding Source, you remain obligated to ensure that it is
- available for as long as needed to satisfy these requirements.
-
- e) Convey the object code using peer-to-peer transmission, provided
- you inform other peers where the object code and Corresponding
- Source of the work are being offered to the general public at no
- charge under subsection 6d.
-
- A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
- A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling. In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage. For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product. A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
- "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source. The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
- If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information. But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
- The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed. Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
- Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
- 7. Additional Terms.
-
- "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law. If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
- When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it. (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.) You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
- Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
- a) Disclaiming warranty or limiting liability differently from the
- terms of sections 15 and 16 of this License; or
-
- b) Requiring preservation of specified reasonable legal notices or
- author attributions in that material or in the Appropriate Legal
- Notices displayed by works containing it; or
-
- c) Prohibiting misrepresentation of the origin of that material, or
- requiring that modified versions of such material be marked in
- reasonable ways as different from the original version; or
-
- d) Limiting the use for publicity purposes of names of licensors or
- authors of the material; or
-
- e) Declining to grant rights under trademark law for use of some
- trade names, trademarks, or service marks; or
-
- f) Requiring indemnification of licensors and authors of that
- material by anyone who conveys the material (or modified versions of
- it) with contractual assumptions of liability to the recipient, for
- any liability that these contractual assumptions directly impose on
- those licensors and authors.
-
- All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10. If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term. If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
- If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
- Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
- 8. Termination.
-
- You may not propagate or modify a covered work except as expressly
-provided under this License. Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
- However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
- Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
- Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License. If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
- 9. Acceptance Not Required for Having Copies.
-
- You are not required to accept this License in order to receive or
-run a copy of the Program. Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance. However,
-nothing other than this License grants you permission to propagate or
-modify any covered work. These actions infringe copyright if you do
-not accept this License. Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
- 10. Automatic Licensing of Downstream Recipients.
-
- Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License. You are not responsible
-for enforcing compliance by third parties with this License.
-
- An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations. If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
- You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License. For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
- 11. Patents.
-
- A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based. The
-work thus licensed is called the contributor's "contributor version".
-
- A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version. For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
- Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
- In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement). To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
- If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients. "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
- If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
- A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License. You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
- Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
- 12. No Surrender of Others' Freedom.
-
- If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all. For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
- 13. Use with the GNU Affero General Public License.
-
- Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work. The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
- 14. Revised Versions of this License.
-
- The Free Software Foundation may publish revised and/or new versions of
-the GNU General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Program specifies that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation. If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
- If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
- Later license versions may give you additional or different
-permissions. However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
- 15. Disclaimer of Warranty.
-
- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. Limitation of Liability.
-
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
- 17. Interpretation of Sections 15 and 16.
-
- If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-
- Copyright (C)
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-
-Also add information on how to contact you by electronic and paper mail.
-
- If the program does terminal interaction, make it output a short
-notice like this when it starts in an interactive mode:
-
- Copyright (C)
- This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, your program's commands
-might be different; for a GUI interface, you would use an "about box".
-
- You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU GPL, see
-.
-
- The GNU General Public License does not permit incorporating your program
-into proprietary programs. If your program is a subroutine library, you
-may consider it more useful to permit linking proprietary applications with
-the library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License. But first, please read
-.
diff --git a/openair3/NEMO_SHO/README b/openair3/NEMO_SHO/README
deleted file mode 100644
index 8753e997a98a334cb74ef025e4577a5713b26c8f..0000000000000000000000000000000000000000
--- a/openair3/NEMO_SHO/README
+++ /dev/null
@@ -1,6 +0,0 @@
-THE APPLY ORDER MUST BE THE FOLLOWING:
-mmipv6-daemon-umip-0.4-nepl-20080108.patch
-mmipv6-daemon-umip-0.4-nepl-mcoa-20080108.patch
-mmipv6-daemon-umip-0.4-sho-20080331.patch
-mmipv6-daemon-umip-0.4-nasmesh-2009-may-12.patch
-
diff --git a/openair3/NEMO_SHO/mipv6-daemon-umip-0.4-nasmesh-2009-may-12.patch b/openair3/NEMO_SHO/mipv6-daemon-umip-0.4-nasmesh-2009-may-12.patch
deleted file mode 100644
index abb8f76f8a31340ec3209cf2e699b38e6bcdd3b1..0000000000000000000000000000000000000000
--- a/openair3/NEMO_SHO/mipv6-daemon-umip-0.4-nasmesh-2009-may-12.patch
+++ /dev/null
@@ -1,301 +0,0 @@
-Only in mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho: config.h
-Only in mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho: config.log
-Only in mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho: config.status
-Only in mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho/libmissing: .deps
-Only in mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho/libmissing: Makefile
-Only in mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho/libnetlink: .deps
-Only in mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho/libnetlink: Makefile
-Only in mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho: Makefile
-Only in mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho/man: Makefile
-Only in mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho/src: .deps
-Only in mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho/src: gram.c
-Only in mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho/src: gram.h
-Only in mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho/src: Makefile
-diff -ur mipv6-daemon-umip-0.4.all.paches.original/src/mh.c mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho/src/mh.c
---- mipv6-daemon-umip-0.4.all.paches.original/src/mh.c 2009-05-12 14:38:53.000000000 +0200
-+++ mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho/src/mh.c 2009-05-12 14:33:25.000000000 +0200
-@@ -816,8 +816,11 @@
- }
-
- pthread_mutex_lock(&mh_sock.send_mutex);
-- setsockopt(mh_sock.fd, IPPROTO_IPV6, IPV6_PKTINFO,
-+ ret = setsockopt(mh_sock.fd, IPPROTO_IPV6, IPV6_PKTINFO,
- &on, sizeof(int));
-+ if (ret < 0)
-+ dbg("setsockopt: %s\n", strerror(errno));
-+
- ret = sendmsg(mh_sock.fd, &msg, 0);
- if (ret < 0)
- dbg("sendmsg: %s\n", strerror(errno));
-Only in mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho/src: mh.c~
-diff -ur mipv6-daemon-umip-0.4.all.paches.original/src/mn.c mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho/src/mn.c
---- mipv6-daemon-umip-0.4.all.paches.original/src/mn.c 2009-05-12 14:38:53.000000000 +0200
-+++ mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho/src/mn.c 2009-05-12 14:33:25.000000000 +0200
-@@ -130,6 +130,8 @@
- * is the BID number. BID must be between
- * BCE_TABLE_MIN and BCE_TABLE_MAX
- */
-+ MDBG("--------------------------------------\n");
-+ MDBG("mcoa_mn_init_rt_table()\n");
- assert(bule);
-
- /* If BID is not assigned, default table is taken */
-@@ -147,6 +149,8 @@
- {
- int ret = -1;
-
-+ MDBG("--------------------------------------\n");
-+ MDBG("mn_block_rule_del()\n");
- if (!(hai->home_block & HOME_ADDR_RULE_BLOCK)) {
- MDBG("blackhole is not set.\n");
- return ret;
-@@ -166,6 +170,8 @@
- {
- int ret = -1;
-
-+ MDBG("--------------------------------------\n");
-+ MDBG("mn_block_rule_add()\n");
- if (hai->home_block & HOME_ADDR_RULE_BLOCK) {
- MDBG("blackhole is already set.\n");
- return ret;
-@@ -182,6 +188,8 @@
-
- static void bul_expire(struct tq_elem *tqe)
- {
-+ MDBG("--------------------------------------\n");
-+ MDBG("bul_expire()\n");
- pthread_rwlock_wrlock(&mn_lock);
- if (!task_interrupted()) {
- struct bulentry *bule = tq_data(tqe, struct bulentry, tqe);
-@@ -205,6 +213,8 @@
- uint16_t flags = e->flags;
- uint16_t bid = e->bid;
-
-+ MDBG("--------------------------------------\n");
-+ MDBG("bule_invalidate()\n");
- if (type != BUL_ENTRY)
- return;
-
-@@ -307,6 +317,8 @@
- struct in6_addr *raddr = &ip6h->ip6_dst;
- struct in6_addr addr;
-
-+ MDBG("--------------------------------------\n");
-+ MDBG("mn_recv_param_prob()\n");
- /* We only handle code 1 & 2 messages. */
- if (ih->icmp6_code != ICMP6_PARAMPROB_NEXTHEADER &&
- ih->icmp6_code != ICMP6_PARAMPROB_OPTION)
-@@ -623,6 +635,8 @@
- */
- static int mn_dereg_bule(struct bulentry *bule)
- {
-+ MDBG("--------------------------------------\n");
-+ MDBG("mn_dereg_bule()\n");
- if (bule->type != NON_MIP_CN_ENTRY) {
- bule->seq++;
- bule->mcoa_dereg = 0;
-@@ -637,6 +651,8 @@
- {
- struct bulentry *bule = vbule;
-
-+ MDBG("--------------------------------------\n");
-+ MDBG("mn_dereg()\n");
- if (bule->type == BUL_ENTRY) {
- if (!(bule->flags & IP6_MH_BU_HOME)) {
- bule->dereg = 1;
-@@ -684,6 +700,8 @@
- {
- int dhaad = dhaad_home_reg_failed(hai);
- int type = FLUSH_VALID;
-+ MDBG("--------------------------------------\n");
-+ MDBG("mn_change_ha()\n");
- if (hai->home_reg_status != HOME_REG_NONE)
- bul_iterate(&hai->bul, _bul_flush, &type);
- syslog(LOG_ERR,
-@@ -820,6 +838,8 @@
- uint32_t valid = PREFIX_LIFETIME_INFINITE;
- int plen = (mha->if_next == hai->if_tunnel ? 128 : hai->plen);
-
-+ MDBG("--------------------------------------\n");
-+ MDBG("mv_hoa\n");
- clock_gettime(CLOCK_REALTIME, &now);
-
- if (hai->lladdr_comp && rta_tb[IFA_CACHEINFO] != NULL) {
-@@ -889,6 +909,8 @@
- {
- struct list_head *l;
- struct prefix_list_entry *pe;
-+ MDBG("--------------------------------------\n");
-+ MDBG("nemo_mr_tnl_routes_add\n");
- list_for_each(l, &hai->mob_net_prefixes) {
- struct prefix_list_entry *p;
- p = list_entry(l, struct prefix_list_entry, list);
-@@ -917,6 +939,8 @@
- int ifindex, int all, int rtable)
- {
- int err = 0;
-+ MDBG("--------------------------------------\n");
-+ MDBG("mn_tnl_state_add\n");
- if (hai->home_reg_status != HOME_REG_NONE) {
- if ((err = mn_ro_pol_add(hai, ifindex, all)) < 0)
- return err;
-@@ -939,6 +963,8 @@
- int ifindex, int rtable)
- {
- struct list_head *l;
-+ MDBG("--------------------------------------\n");
-+ MDBG("nemo_mr_tnl_routes_del\n");
- list_for_each(l, &hai->mob_net_prefixes) {
- struct prefix_list_entry *p;
- p = list_entry(l, struct prefix_list_entry, list);
-@@ -1001,6 +1027,8 @@
- struct home_addr_info *hai,
- struct timespec *lifetime)
- {
-+ MDBG("--------------------------------------\n");
-+ MDBG("process_first_home_bu\n");
- int err = 0;
- assert(hai->current_coa);
- bule->type = BUL_ENTRY;
-@@ -1090,6 +1118,8 @@
- int homereg_expired = 0;
- movement_t type_movement = MIP6_TYPE_MOVEMENT_UNKNOWN;
-
-+ MDBG("--------------------------------------\n");
-+ MDBG("mn_send_home_bu\n");
- TRACE;
- assert(hai->current_coa);
-
-@@ -1285,6 +1315,8 @@
-
- void mn_send_cn_bu(struct bulentry *bule)
- {
-+ MDBG("--------------------------------------\n");
-+ MDBG("mn_send_cn_bu\n");
- /* Rate limiting CN registration binding updates
- is necessary for multihomed MNs */
- if (mn_bu_ratelimit(bule))
-@@ -1487,6 +1519,8 @@
- struct timespec now, ba_lifetime, br_adv;
- uint16_t seqno, bid;
-
-+ MDBG("--------------------------------------\n");
-+ MDBG("mn_recv_ba\n");
- TRACE;
-
- if (len < sizeof(struct ip6_mh_binding_ack) ||
-@@ -1875,6 +1909,8 @@
- struct home_addr_info *hai,
- int replace)
- {
-+ MDBG("--------------------------------------\n");
-+ MDBG("mcoa_iface_dflt_hoa_rule_del\n");
- /* MCoA: Delete the default HoA rule */
- rule_del(NULL, bule->bid, IP6_RULE_PRIO_MIP6_HOA_OUT,
- 0, RTN_UNICAST, &hai->hoa.addr, 128,
-@@ -1900,6 +1936,8 @@
- struct prefix_list_entry *p,
- int replace)
- {
-+ MDBG("--------------------------------------\n");
-+ MDBG("mcoa_iface_dflt_mnp_rules_del\n");
- /* MCoA: Delete the default MNP rule */
- rule_del(NULL, bule->bid, IP6_RULE_PRIO_MIP6_FWD_MCOA,
- 0, RTN_UNICAST, &p->ple_prefix, p->ple_plen,
-@@ -1926,6 +1964,8 @@
- struct list_head *l;
- int delete_dflt_mnp = 0;
-
-+ MDBG("--------------------------------------\n");
-+ MDBG("mcoa_iface_rules_del\n");
- bule = bul_get(hai, NULL, &hai->ha_addr, bid);
- if (!hai->reg_mcoa || (bule && !bule->rules))
- return NULL;
-@@ -1977,6 +2017,8 @@
- {
- struct list_head *l;
-
-+ MDBG("--------------------------------------\n");
-+ MDBG("mcoa_mn_rules_del\n");
- list_for_each(l, &hinfo->mcoa) {
- struct mn_addr *iface = NULL;
- iface = list_entry(l, struct mn_addr, list);
-@@ -2006,6 +2048,8 @@
- struct list_head *l;
- uint8_t prio;
-
-+ MDBG("--------------------------------------\n");
-+ MDBG("mcoa_iface_rules_add\n");
- bule = bul_get(hai, NULL, &hai->ha_addr, bid);
- if (!bid || !hai->reg_mcoa || !bule || (bule && bule->rules))
- return 0;
-@@ -2088,6 +2132,8 @@
- {
- struct list_head *l;
-
-+ MDBG("--------------------------------------\n");
-+ MDBG("nemo_mr_rules_del\n");
- list_for_each(l, &hinfo->mob_net_prefixes) {
- struct prefix_list_entry *p = NULL;
- p = list_entry(l, struct prefix_list_entry, list);
-@@ -2111,6 +2157,8 @@
- struct prefix_list_entry *pe = NULL;
- struct list_head *l;
-
-+ MDBG("--------------------------------------\n");
-+ MDBG("nemo_mr_rules_add\n");
- list_for_each(l, &hinfo->mob_net_prefixes) {
- struct prefix_list_entry *p = NULL;
- p = list_entry(l, struct prefix_list_entry, list);
-@@ -2164,6 +2212,8 @@
- struct flag_hoa_args arg;
- int plen = (hai->hoa.iif == hai->if_tunnel ? 128 : hai->plen);
-
-+ MDBG("--------------------------------------\n");
-+ MDBG("clean_home_addr_info\n");
- list_del(&hai->list);
- if (hai->mob_rtr)
- nemo_mr_rules_del(hai);
-@@ -2538,6 +2588,8 @@
- struct mv_hoa_args mha;
- struct list_head *l;
-
-+ MDBG("--------------------------------------\n");
-+ MDBG("mn_move\n");
- mha.target = hai;
-
- TRACE;
-Only in mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho/src: mn.c~
-diff -ur mipv6-daemon-umip-0.4.all.paches.original/src/movement.c mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho/src/movement.c
---- mipv6-daemon-umip-0.4.all.paches.original/src/movement.c 2009-05-12 14:38:53.000000000 +0200
-+++ mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho/src/movement.c 2009-05-12 14:33:25.000000000 +0200
-@@ -611,7 +611,9 @@
- memset(lladdr, 0, sizeof(struct in6_addr));
- uint8_t *eui = lladdr->s6_addr + 8;
- switch (iface_type) {
-- case ARPHRD_ETHER:
-+ case ARPHRD_EUROPENAIRMESH:
-+ memcpy(eui, hwa, 8);
-+ break;
- case ARPHRD_IEEE802:
- case ARPHRD_IEEE802_TR:
- case ARPHRD_IEEE80211:
-Only in mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho/src: movement.c~
-diff -ur mipv6-daemon-umip-0.4.all.paches.original/src/ndisc.h mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho/src/ndisc.h
---- mipv6-daemon-umip-0.4.all.paches.original/src/ndisc.h 2009-05-12 14:38:38.000000000 +0200
-+++ mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho/src/ndisc.h 2009-05-12 14:33:25.000000000 +0200
-@@ -11,6 +11,8 @@
- {
- switch (iface_type) {
- /* supported physical devices */
-+ case ARPHRD_EUROPENAIRMESH:
-+ return 8;
- case ARPHRD_ETHER:
- case ARPHRD_IEEE802:
- case ARPHRD_IEEE802_TR:
-Only in mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho/src: ndisc.h~
-Only in mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho/src: pmgr.c
-Only in mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho/src: pmgr.h
-Only in mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho/src: scan.c
-Only in mipv6-daemon-umip-0.4_patch_nepl_mcoa_sho: stamp-h1
-Only in mipv6-daemon-umip-0.4.all.paches.original: ZE_PATCH.patch
diff --git a/openair3/NEMO_SHO/mipv6-daemon-umip-0.4-nepl-20080108.patch b/openair3/NEMO_SHO/mipv6-daemon-umip-0.4-nepl-20080108.patch
deleted file mode 100755
index 7d70c0d531afe6c1b3c27f979942812262204c4d..0000000000000000000000000000000000000000
--- a/openair3/NEMO_SHO/mipv6-daemon-umip-0.4-nepl-20080108.patch
+++ /dev/null
@@ -1,2862 +0,0 @@
-diff -r a7e20b0b5c43 AUTHORS
---- a/AUTHORS Wed Nov 28 16:43:32 2007 +0100
-+++ b/AUTHORS Tue Jan 08 11:28:48 2008 +0100
-@@ -5,3 +5,14 @@ Petander. Code has been contributed by
- Petander. Code has been contributed by several individuals. See
- THANKS for listing. See libnetlink/README for information regarding
- libnetlink.
-+
-+The NEMO Basic support code is developed by Ville Nuorvala
-+ in co-operation with the Nautilus6/WIDE
-+project (http://www.nautilus6.org).
-+
-+The NEMO Basic Support code has been ported to UMIP by Romain KUNTZ
-+ and received contributions from the
-+following people:
-+- Sebastien DECUGIS (Nautilus6): IPsec support for NEMO
-+- Arnaud EBALARD (EADS): fixes for Big Endian architectures and
-+ improvements of the NEMO debug messages.
-diff -r a7e20b0b5c43 BUGS
---- a/BUGS Wed Nov 28 16:43:32 2007 +0100
-+++ b/BUGS Tue Jan 08 11:28:48 2008 +0100
-@@ -17,3 +17,11 @@ Mobile Node issues
- * Multihoming support hasn't been very thoroughly tested and should
- therefore be considered developmental code. However, it is a lot
- more stable than in the Release Candidates.
-+
-+NEMO issues
-+-----------
-+
-+* The Mobile Router's home address may only be on the egress interface.
-+
-+* Dynamic routing protocols between the Home Agent and Mobile Router
-+ are not yet supported.
-diff -r a7e20b0b5c43 COPYING.NEMO
---- /dev/null Thu Jan 01 00:00:00 1970 +0000
-+++ b/COPYING.NEMO Tue Jan 08 11:28:48 2008 +0100
-@@ -0,0 +1,13 @@
-+Cisco and Nokia have both published IPR notices regarding RFC 3963
-+"Network Mobility (NEMO) Basic Support Protocol."
-+
-+Cisco has agreed not to assert its patents against any party agreeing with the
-+terms in its IPR notice.
-+
-+Likewise, Nokia has agreed not to assert its patents against Open Source
-+implementations of the specification.
-+
-+For further information, please read
-+licenses/cisco-ipr-draft-ietf-nemo-basic-support-03.txt and
-+licenses/nokia-ipr-draft-ietf-nemo-basic-support.txt.
-+
-diff -r a7e20b0b5c43 INSTALL
---- a/INSTALL Wed Nov 28 16:43:32 2007 +0100
-+++ b/INSTALL Tue Jan 08 11:28:48 2008 +0100
-@@ -45,6 +45,8 @@ 4. Run 'make install'. Executables shou
- further information on how to configure your node. Also take a
- look at the example configuration files in the extras directory.
-
-+ For comments about NEMO check README.NEMO.
-+
- For comments about IPsec support check README.IPsec.
-
- 5. A startup script
-diff -r a7e20b0b5c43 README
---- a/README Wed Nov 28 16:43:32 2007 +0100
-+++ b/README Tue Jan 08 11:28:48 2008 +0100
-@@ -2,6 +2,9 @@ MIPL Mobile IPv6 for Linux
-
- MIPL Mobile IPv6 for Linux is an implementation of the Mobility
- Support in IP version 6 (RFC 3775).
-+
-+ It also supports Network Mobility with the NEMO Basic Support
-+ implementation (RFC 3963).
-
- This user space part works together with Mobile IPv6 enabled Linux
- kernels. See INSTALL and any other documents referred there for
-diff -r a7e20b0b5c43 README.NEMO
---- /dev/null Thu Jan 01 00:00:00 1970 +0000
-+++ b/README.NEMO Tue Jan 08 11:28:48 2008 +0100
-@@ -0,0 +1,18 @@
-+README for NEMO Basic Support
-+-----------------------------
-+
-+Here are a few things you need to keep in mind when setting up Network
-+Mobility:
-+
-+The MR is a router so you need to set
-+/proc/sys/net/ipv6/conf/all/forwarding to 1 to make sure it will forward
-+packets between its ingress and egress interfaces.
-+
-+With static routing the HA and other routers on the home link might need some
-+additional boot-strapping. If the MR has a physical home link that it may be
-+attached to, the other routers must be pre-configured with routes to the MR's
-+Mobile Network Prefixes via the MR's home address. This ensures packets will
-+be forwarded correctly also when the MR is at home.
-+
-+To be able to support NEMO DHAAD the HA needs to have AdvHomeAgentInfo and
-+AdvMobRtrSupportFlag turned on in radvd.conf.
-diff -r a7e20b0b5c43 include/netinet/icmp6.h
---- a/include/netinet/icmp6.h Wed Nov 28 16:43:32 2007 +0100
-+++ b/include/netinet/icmp6.h Tue Jan 08 11:28:48 2008 +0100
-@@ -27,7 +27,13 @@ struct mip_dhaad_req { /* Dynamic HA Ad
- #define mip_dhreq_code mip_dhreq_hdr.icmp6_code
- #define mip_dhreq_cksum mip_dhreq_hdr.icmp6_cksum
- #define mip_dhreq_id mip_dhreq_hdr.icmp6_data16[0]
--#define mip_dhreq_reserved mip_dhreq_hdr.icmp6_data16[1]
-+#define mip_dhreq_flags_reserved mip_dhreq_hdr.icmp6_data16[1]
-+
-+#if BYTE_ORDER == BIG_ENDIAN
-+#define MIP_DHREQ_FLAG_SUPPORT_MR 0x8000
-+#else /* BYTE_ORDER == LITTLE_ENDIAN */
-+#define MIP_DHREQ_FLAG_SUPPORT_MR 0x0080
-+#endif
- #endif
-
- #ifndef HAVE_STRUCT_MIP_DHAAD_REP
-@@ -40,7 +46,13 @@ struct mip_dhaad_rep { /* HA Address Di
- #define mip_dhrep_code mip_dhrep_hdr.icmp6_code
- #define mip_dhrep_cksum mip_dhrep_hdr.icmp6_cksum
- #define mip_dhrep_id mip_dhrep_hdr.icmp6_data16[0]
--#define mip_dhrep_reserved mip_dhrep_hdr.icmp6_data16[1]
-+#define mip_dhrep_flags_reserved mip_dhrep_hdr.icmp6_data16[1]
-+
-+#if BYTE_ORDER == BIG_ENDIAN
-+#define MIP_DHREP_FLAG_SUPPORT_MR 0x8000
-+#else /* BYTE_ORDER == LITTLE_ENDIAN */
-+#define MIP_DHREP_FLAG_SUPPORT_MR 0x0080
-+#endif
- #endif
-
- #ifndef HAVE_STRUCT_MIP_PREFIX_SOLICIT
-@@ -89,10 +101,20 @@ struct nd_opt_homeagent_info { /* Home A
- struct nd_opt_homeagent_info { /* Home Agent information */
- uint8_t nd_opt_hai_type;
- uint8_t nd_opt_hai_len;
-- uint16_t nd_opt_hai_reserved;
-+ uint16_t nd_opt_hai_flags_reserved;
- uint16_t nd_opt_hai_preference;
- uint16_t nd_opt_hai_lifetime;
- };
- #endif
-
-+#define nd_opt_hai_reserved nd_opt_hai_flags_reserved
-+
-+#ifndef ND_OPT_HAI_FLAG_SUPPORT_MR
-+#if BYTE_ORDER == BIG_ENDIAN
-+#define ND_OPT_HAI_FLAG_SUPPORT_MR 0x8000
-+#else /* BYTE_ORDER == LITTLE_ENDIAN */
-+#define ND_OPT_HAI_FLAG_SUPPORT_MR 0x0080
-+#endif
-+#endif
-+
- #endif /* netinet/icmp6.h */
-diff -r a7e20b0b5c43 licenses/cisco-ipr-draft-ietf-nemo-basic-support-03.txt
---- /dev/null Thu Jan 01 00:00:00 1970 +0000
-+++ b/licenses/cisco-ipr-draft-ietf-nemo-basic-support-03.txt Tue Jan 08 11:28:48 2008 +0100
-@@ -0,0 +1,41 @@
-+Title: Cisco Systems' Updated Statement about IPR claimed in
-+ draft-ietf-nemo-basic-support-03.txt
-+Received 25 October 2004
-+From: Robert Barr
-+
-+This statement updates the IPR statement filed by Cisco on June 20, 2003 for
-+draft-ietf-nemo-basic-support-00.txt.
-+
-+Cisco is the owner of US Patent No. 6,636,498 and at least one pending
-+patent application
-+relating to the subject matter of draft-ietf-nemo-basic-support-03.txt
-+"Network Mobility (NEMO) Basic Support Protocol" .
-+If a standard relating to this subject matter is adopted by IETF and any
-+claims
-+of any issued Cisco patents are necessary for practicing this standard, any
-+party will be able to obtain a license from Cisco to use any such patent
-+claims under openly specified, reasonable, non-discriminatory terms, with
-+reciprocity, to implement and fully comply with the standard.
-+
-+The reasonable non-discriminatory terms are:
-+
-+If this standard is adopted, Cisco will not assert any patents owned or
-+controlled by Cisco against any party for making, using, selling, importing
-+or offering for sale a product that implements the standard, provided,
-+however that Cisco retains the right to assert its patents (including the
-+right to claim past royalties) against any party that asserts a patent it
-+owns or controls (either directly or indirectly) against Cisco or any of
-+Cisco's affiliates or successors in title; and Cisco retains the right to
-+assert its patents against any product or portion thereof that is not
-+necessary for compliance with the standard.
-+
-+Royalty-bearing licenses will be available to anyone who prefers that
-+option.
-+
-+For information contact:
-+
-+Robert Barr
-+Worldwide Patent Counsel
-+Cisco Systems
-+408-525-9706
-+rbarr@cisco.com
-diff -r a7e20b0b5c43 licenses/nokia-ipr-draft-ietf-nemo-basic-support.txt
---- /dev/null Thu Jan 01 00:00:00 1970 +0000
-+++ b/licenses/nokia-ipr-draft-ietf-nemo-basic-support.txt Tue Jan 08 11:28:48 2008 +0100
-@@ -0,0 +1,26 @@
-+Title: Nokia Corporation's statement about IPR claimed in draft-ietf-nemo-basic-support
-+Received: July 1, 2003
-+From: Heikki Huttunen
-+
-+This is to advise the IETF that Nokia believes the Nokia patent application "Mobile Router
-+Support for IPv6", US10/295014, WO03/043226 may be relevant to Nemo Basic Support Protocol
-+.
-+
-+Regarding internet draft "draft-ietf-nemo-basic-support", to the extent this draft is
-+included into final IETF standard specification, Nokia agrees not to assert those claims
-+in Nokia patents that apply to this draft and that are technically necessary to implement
-+the IETF standard specification against any other party in respect of its implementation of
-+the specification, if only practiced under any software distributed under the present terms
-+of GNU GENERAL PUBLIC LICENSE (http://www.fsf.org/copyleft/gpl.html) or under license terms
-+that conform to the present open source definition (http://www.opensource.org/osd.html) and
-+provided that the party relying on this commitment does not assert its patents against Nokia.
-+
-+Otherwise general Nokia Statement on Patent Licensing (http://www.ietf.org/ietf/IPR/NOKIA)
-+applies to this submission.
-+
-+
-+Heikki Huttunen
-+Director, Licensing
-+Nokia Corporation
-+P.O Box 86, FIN-24101 Salo, Finland
-+Phone: +358 (0) 7180 41202, Fax: +358 (0) 7180 44275
-diff -r a7e20b0b5c43 man/mip6d.conf.tmpl
---- a/man/mip6d.conf.tmpl Wed Nov 28 16:43:32 2007 +0100
-+++ b/man/mip6d.conf.tmpl Tue Jan 08 11:28:48 2008 +0100
-@@ -1,12 +1,12 @@
- .\" $Id: mip6d.conf.tmpl 1.33 06/05/12 11:48:36+03:00 vnuorval@tcs.hut.fi $
--.TH mip6d.conf 5 "January 31, 2006" "" "Mobile IPv6 Daemon Configuration"
-+.TH mip6d.conf 5 "January 31, 2006" "" "Mobile IPv6 and NEMO Daemon Configuration"
- .SH NAME
--mip6d.conf \- MIPL Mobile IPv6 Configuration file
-+mip6d.conf \- MIPL Mobile IPv6 and NEMO Configuration file
- .SH SYNOPSIS
- .B %etc%/mip6d.conf
- .sp
- .SH DESCRIPTION
--MIPL Mobile IPv6 daemon's configuration file
-+MIPL Mobile IPv6 and NEMO daemon's configuration file
- .P
- Below is a list of currently supported configuration options. All
- configuration lines are terminated with a semicolon. Sub-sections are
-@@ -184,10 +184,29 @@ Default: 86400
- Default: 86400
-
- .TP
--.BR "BindingAclPolicy " "address " "allow | deny"
-+.BR "HaAcceptMobRtr enabled | disabled"
-
--Defines if a MN is allowed to register with the HA or not. The MN home address
--of the MN is given in the address field."
-+Indicates if the HA accepts Mobile Router bindings.
-+
-+Default: disabled;
-+
-+.TP
-+.BR "HaServedPrefix " "prefix/length" ";"
-+
-+Prefix is an IPv6 prefix and length is the prefix length. Defines the whole
-+aggregated or extended prefix the HA serves. This option is only used for MR
-+bindings and is only needed if the MRs derive their Home Addresses from their
-+Mobile Network Prefixes, instead of one of the home link prefixes.
-+
-+.TP
-+.BR "BindingAclPolicy " "address MNP list " "allow | deny"
-+
-+Defines if a MN is allowed to register with the HA or not. The home address
-+of the MN is given in the address field. The mobile network prefixes
-+belonging a NEMO Mobile Router are listed in the MNP list. The list can either
-+be an empty string or a comma separated list of network prefixes
-+enclosed in braces, for example:
-+.B "(3ffe:2620:6:3::/64, 3ffe:2620:6:4::/64)"
-
- .TP
- .BR "DefaultBindingAclPolicy allow | deny"
-@@ -254,6 +273,13 @@ Default: disabled
- Default: disabled
-
- .TP
-+.BR "MobRtrUseExplicitMode enabled | disabled"
-+
-+Toggles between explicit or implicit mode home registrations in the MR.
-+
-+Default: enabled
-+
-+.TP
- .BR "UseCnBuAck " "boolean" ";"
-
- Indicates if the Acknowledge bit should be set in Binding Updates sent to
-@@ -299,7 +325,7 @@ Default: disabled;
- .TP
- .nf
- .BR "MnHomeLink " "name " "{"
--.BR " HomeAddress " "address/length" ";"
-+.BR " HomeAddress " "address/length MNP list" ";"
- .BR " HomeAgentAddress " "address" ";"
- .BR " MnRoPolicy ..."
- .BR " ..."
-@@ -317,11 +343,14 @@ definitions. All the home link specific
- definitions. All the home link specific definitions are detailed below:
-
- .TP
--.BR "HomeAddress " "address/length" ";"
-+.BR "HomeAddress " "address/length MNP list" ";"
-
- Address is an IPv6 address, and length the prefix length of the
--address, usually 64. This option must be included in a home link
--definition.
-+address, usually 64. The MNP list contains the mobile network prefixes
-+belonging to that particular NEMO Mobile Router. The MNP list is of the
-+same format as in
-+.B "BindingAclPolicy."
-+This option must be included in a home link definition.
-
- .TP
- .BR "HomeAgentAddress " "address" ";"
-@@ -330,6 +359,13 @@ if it is the unspecified address ::.
- if it is the unspecified address ::.
-
- Default: ::
-+
-+.TP
-+.BR "IsMobRtr enabled | disabled"
-+
-+Defines if the MN is a NEMO MR.
-+
-+Default: disabled
-
- .TP
- The route optimization policies are of the form:
-@@ -351,6 +387,49 @@ matching this entry.
- matching this entry.
-
- .SH EXAMPLES
-+
-+.TP
-+.BR "A NEMO Home Agent example:"
-+
-+.nf
-+NodeConfig HA;
-+
-+Interface "eth0";
-+
-+HaAcceptMobRtr enabled;
-+
-+HaServedPrefix 3ffe:2620:6::/48;
-+
-+DefaultBindingAclPolicy deny;
-+BindingAclPolicy 3ffe:2620:6:1::1234 (3ffe:2620:6:2::/64, 3ffe:2620:6:3::/64) allow;
-+BindingAclPolicy 3ffe:2620:6:1::1235 allow;
-+
-+UseMnHaIPsec disabled;
-+.fi
-+
-+.TP
-+.BR "A NEMO Mobile Router example:"
-+
-+.nf
-+NodeConfig MN;
-+
-+DoRouteOptimizationCN disabled;
-+DoRouteOptimizationMN disabled;
-+
-+Interface "eth0";
-+
-+MnRouterProbes 1;
-+
-+MobRtrUseExplicitMode enabled;
-+
-+MnHomeLink "eth0" {
-+ IsMobRtr enabled;
-+ HomeAgentAddress 3ffe:2620:6:1::1;
-+ HomeAddress 3ffe:2620:6:1::1234/64 (3ffe:2620:6:2::/64, 3ffe:2620:6:3::/64);
-+}
-+
-+UseMnHaIPsec disabled;
-+.fi
-
- .TP
- .BR "A Correspondent Node example:"
-diff -r a7e20b0b5c43 man/mip6d.tmpl
---- a/man/mip6d.tmpl Wed Nov 28 16:43:32 2007 +0100
-+++ b/man/mip6d.tmpl Tue Jan 08 11:28:48 2008 +0100
-@@ -1,13 +1,13 @@
- .\" $Id: mip6d.tmpl 1.4 05/05/16 13:13:41+03:00 anttit@tcs.hut.fi $
--.TH mip6d 1 "May 16, 2005" "" "Mobile IPv6 Daemon"
-+.TH mip6d 1 "May 16, 2005" "" "Mobile IPv6 and NEMO Daemon"
- .SH NAME
--mip6d \- MIPL Mobile IPv6 protocol implementation
-+mip6d \- MIPL Mobile IPv6 and NEMO Basic Support protocol implementation
- .SH SYNOPSIS
- .B mip6d [options]
- .sp
- .SH DESCRIPTION
-
--Mobile IPv6 implementation
-+Mobile IPv6 and NEMO Basic Support implementation
-
- .SH OPTIONS
- .IP "\fB\-V, \-\-version\fP"
-@@ -41,3 +41,5 @@ RFC3775: Mobility Support in IPv6,
- .PP
- RFC3776: Using IPsec to Protect Mobile IPv6 Signaling Between Mobile
- Nodes and Home Agents
-+.PP
-+RFC3963: Network Mobility (NEMO) Basic Support Protocol
-diff -r a7e20b0b5c43 src/bcache.c
---- a/src/bcache.c Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/bcache.c Tue Jan 08 11:28:48 2008 +0100
-@@ -39,6 +39,7 @@
- #include "mh.h"
- #include "cn.h"
- #include "vt.h"
-+#include "prefix.h"
-
- #define BCACHE_BUCKETS 32
-
-@@ -63,6 +64,7 @@ void dump_bce(void *bce, void *os)
- {
- struct bcentry *e = (struct bcentry *)bce;
- FILE *out = (FILE *)os;
-+ int mnpcount = 0;
-
- fprintf(out, " == Binding Cache entry ");
-
-@@ -87,6 +89,37 @@ void dump_bce(void *bce, void *os)
- NIP6ADDR(&e->our_addr));
- fprintf(out, " lifetime %ld\n ", e->lifetime.tv_sec);
- fprintf(out, " seqno %d\n", e->seqno);
-+
-+ if (e->flags & IP6_MH_BA_MR) {
-+ struct list_head *list;
-+
-+ /* MR registration type */
-+ fprintf(out, "MR Registration type: ");
-+ switch(e->nemo_type) {
-+ case BCE_NEMO_EXPLICIT:
-+ fprintf(out, "explicit.\n");
-+ break;
-+ case BCE_NEMO_IMPLICIT:
-+ fprintf(out, "implicit.\n");
-+ break;
-+ default:
-+ fprintf(out, "unknown.\n");
-+ }
-+
-+ /* Mobile Network prefixes */
-+ fprintf(out, "MR Mobile network prefixes: ");
-+ list_for_each(list, &e->mob_net_prefixes) {
-+ struct prefix_list_entry *p;
-+ p = list_entry(list, struct prefix_list_entry, list);
-+ if (mnpcount)
-+ fprintf(out, " ");
-+ fprintf(out, "%x:%x:%x:%x:%x:%x:%x:%x/%d\n",
-+ NIP6ADDR(&p->ple_prefix), p->ple_plen);
-+ mnpcount++;
-+ }
-+ if (!mnpcount)
-+ fprintf(out, " none registered.\n");
-+ }
-
- fflush(out);
- }
-@@ -144,6 +177,7 @@ struct bcentry *bcache_alloc(int type)
- }
- memset(tmp, 0, sizeof(*tmp));
- INIT_LIST_HEAD(&tmp->tqe.list);
-+ INIT_LIST_HEAD(&tmp->mob_net_prefixes);
- return tmp;
- }
-
-@@ -158,6 +192,7 @@ void bcache_free(struct bcentry *bce)
- /* This function should really return allocated space to free
- * pool. */
- pthread_rwlock_destroy(&bce->lock);
-+ prefix_list_free(&bce->mob_net_prefixes);
- free(bce);
- }
-
-diff -r a7e20b0b5c43 src/bcache.h
---- a/src/bcache.h Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/bcache.h Tue Jan 08 11:28:48 2008 +0100
-@@ -18,7 +18,8 @@ struct bcentry {
-
- uint16_t nonce_coa;
- uint16_t nonce_hoa;
-- int type; /* Entry type */
-+ uint16_t type; /* Entry type */
-+ uint16_t nemo_type; /* NEMO registration type */
- int unreach; /* ICMP dest unreach count */
- int tunnel; /* Tunnel interface index */
- int link; /* Home link interface index */
-@@ -33,6 +34,8 @@ struct bcentry {
- struct tq_elem tqe; /* Timer queue entry for expire */
-
- void (*cleanup)(struct bcentry *bce); /* Clean up bce data */
-+
-+ struct list_head mob_net_prefixes;
- };
-
- #define BCE_NONCE_BLOCK 0
-@@ -40,6 +43,10 @@ struct bcentry {
- #define BCE_CACHED 2
- #define BCE_CACHE_DYING 3
- #define BCE_DAD 4
-+
-+#define BCE_NEMO_EXPLICIT 1
-+#define BCE_NEMO_IMPLICIT 2
-+#define BCE_NEMO_DYNAMIC 3
-
- struct bcentry *bcache_alloc(int type);
-
-diff -r a7e20b0b5c43 src/bul.c
---- a/src/bul.c Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/bul.c Tue Jan 08 11:28:48 2008 +0100
-@@ -103,9 +103,11 @@ void dump_bule(void *bule, void *os)
- if (e->flags & IP6_MH_BU_ACK)
- fprintf(out, "IP6_MH_BU_ACK ");
- if (e->flags & IP6_MH_BU_LLOCAL)
-- fprintf(out, "IP6_MH_BU_LLOCAL");
-+ fprintf(out, "IP6_MH_BU_LLOCAL ");
- if (e->flags & IP6_MH_BU_KEYM)
-- fprintf(out, "IP6_MH_BU_KEYM");
-+ fprintf(out, "IP6_MH_BU_KEYM ");
-+ if (e->flags & IP6_MH_BU_MR)
-+ fprintf(out, "IP6_MH_BU_MR");
-
- fprintf(out, "\n");
- fflush(out);
-@@ -184,7 +186,8 @@ int bul_add(struct bulentry *bule)
- goto home_bul_free;
- } else if (bule->type == NON_MIP_CN_ENTRY) {
- if (bule->flags & IP6_MH_BU_HOME) {
-- if (xfrm_block_hoa(hai) < 0)
-+ if (xfrm_block_hoa(hai) < 0 ||
-+ (hai->mob_rtr && xfrm_block_ra(hai) < 0))
- goto home_bul_free;
- }
- }
-@@ -231,6 +234,10 @@ void bul_delete(struct bulentry *bule)
- xfrm_unblock_link(hai);
- if (hai->home_block & HOME_ADDR_BLOCK)
- xfrm_unblock_hoa(hai);
-+ if (hai->home_block & NEMO_RA_BLOCK)
-+ xfrm_unblock_ra(hai);
-+ if (hai->home_block & NEMO_FWD_BLOCK)
-+ xfrm_unblock_fwd(hai);
- }
- }
- while (bule->ext_cleanup)
-diff -r a7e20b0b5c43 src/cn.c
---- a/src/cn.c Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/cn.c Tue Jan 08 11:28:48 2008 +0100
-@@ -177,8 +177,8 @@ void cn_recv_bu(const struct ip6_mh *mh,
- non_ind = mh_opt(&bu->ip6mhbu_hdr, &mh_opts, IP6_MHOPT_NONCEID);
- bce = bcache_get(out.src, out.dst);
- if (bce) {
-- if ((bce->flags^bu_flags) & IP6_MH_BU_HOME) {
-- /* H-bit mismatch, flags changed */
-+ if ((bce->flags^bu_flags) & (IP6_MH_BU_HOME|IP6_MH_BU_MR)) {
-+ /* H-bit or R-bit mismatch, flags changed */
- bcache_release_entry(bce);
- bce = NULL;
- status = IP6_MH_BAS_REG_NOT_ALLOWED;
-@@ -221,9 +221,15 @@ void cn_recv_bu(const struct ip6_mh *mh,
- /* else get rid of it */
- bcache_delete(out.src, out.dst);
- }
-- } else if (bu_flags & IP6_MH_BU_HOME) {
-- status = IP6_MH_BAS_HA_NOT_SUPPORTED;
-- goto send_nack;
-+ } else {
-+ if (bu_flags & IP6_MH_BU_HOME) {
-+ status = IP6_MH_BAS_HA_NOT_SUPPORTED;
-+ goto send_nack;
-+ }
-+ if (bu_flags & IP6_MH_BU_MR) {
-+ status = IP6_MH_BAS_MR_OP_NOT_PERMITTED;
-+ goto send_nack;
-+ }
- }
- status = conf.pmgr.discard_binding(out.dst, out.bind_coa,
- out.src, bu, len);
-diff -r a7e20b0b5c43 src/conf.c
---- a/src/conf.c Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/conf.c Tue Jan 08 11:28:48 2008 +0100
-@@ -212,6 +212,7 @@ static void conf_default(struct mip6_con
- INIT_LIST_HEAD(&c->home_addrs);
- c->MoveModulePath = NULL; /* internal */
- c->DoRouteOptimizationMN = 1;
-+ c->MobRtrUseExplicitMode = 1;
- c->SendMobPfxSols = 1;
- c->OptimisticHandoff = 0;
-
-@@ -221,6 +222,7 @@ static void conf_default(struct mip6_con
- c->MaxMobPfxAdvInterval = 86400; /* seconds */
- c->MinMobPfxAdvInterval = 600; /* seconds */
- c->HaMaxBindingLife = MAX_BINDING_LIFETIME;
-+ INIT_LIST_HEAD(&c->nemo_ha_served_prefixes);
-
- /* CN bindings */
- c->DoRouteOptimizationCN = 1;
-@@ -304,6 +306,8 @@ void conf_show(struct mip6_config *c)
- CONF_BOOL_STR(c->MnDiscardHaParamProb));
- dbg("SendMobPfxSols = %s\n", CONF_BOOL_STR(c->SendMobPfxSols));
- dbg("OptimisticHandoff = %s\n", CONF_BOOL_STR(c->OptimisticHandoff));
-+ dbg("MobRtrUseExplicitMode = %s\n",
-+ CONF_BOOL_STR(c->MobRtrUseExplicitMode));
-
- /* HA options */
- dbg("SendMobPfxAdvs = %s\n", CONF_BOOL_STR(c->SendMobPfxAdvs));
-@@ -312,7 +316,8 @@ void conf_show(struct mip6_config *c)
- dbg("MaxMobPfxAdvInterval = %u\n", c->MaxMobPfxAdvInterval);
- dbg("MinMobPfxAdvInterval = %u\n", c->MinMobPfxAdvInterval);
- dbg("HaMaxBindingLife = %u\n", c->HaMaxBindingLife);
--
-+ dbg("HaAcceptMobRtr = %s\n", CONF_BOOL_STR(c->HaAcceptMobRtr));
-+
- /* CN options */
- dbg("DoRouteOptimizationCN = %s\n",
- CONF_BOOL_STR(c->DoRouteOptimizationCN));
-diff -r a7e20b0b5c43 src/conf.h
---- a/src/conf.h Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/conf.h Tue Jan 08 11:28:48 2008 +0100
-@@ -39,6 +39,7 @@ struct mip6_config {
- struct list_head home_addrs;
- char *MoveModulePath;
- uint16_t CnBuAck;
-+ char MobRtrUseExplicitMode;
- char DoRouteOptimizationMN;
- char MnUseAllInterfaces;
- char MnDiscardHaParamProb;
-@@ -46,15 +47,16 @@ struct mip6_config {
- char OptimisticHandoff;
-
- /* HA options */
-+ char HaAcceptMobRtr;
- char SendMobPfxAdvs;
- char SendUnsolMobPfxAdvs;
- unsigned int MaxMobPfxAdvInterval;
- unsigned int MinMobPfxAdvInterval;
- unsigned int HaMaxBindingLife;
-+ struct list_head nemo_ha_served_prefixes;
-
- /* CN options */
- char DoRouteOptimizationCN;
--
- };
-
- struct net_iface {
-diff -r a7e20b0b5c43 src/dhaad_ha.c
---- a/src/dhaad_ha.c Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/dhaad_ha.c Tue Jan 08 11:28:48 2008 +0100
-@@ -83,8 +83,8 @@ static void dhaad_expire_halist(struct t
- pthread_rwlock_unlock(&ha_lock);
- }
-
--void dhaad_insert_halist(struct ha_interface *i,
-- uint16_t key, uint16_t life_sec,
-+void dhaad_insert_halist(struct ha_interface *i, uint16_t key,
-+ uint16_t life_sec, uint16_t flags,
- struct nd_opt_prefix_info *pinfo,
- const struct in6_addr *lladdr)
- {
-@@ -110,6 +110,7 @@ void dhaad_insert_halist(struct ha_inter
- return;
- }
- memset(ha, 0, sizeof(*ha));
-+ ha->flags = flags;
- ha->iface = i;
- ha->addr = *addr;
- INIT_LIST_HEAD(&ha->tqe.list);
-@@ -136,18 +137,22 @@ void dhaad_insert_halist(struct ha_inter
- return;
- }
-
--static int dhaad_get_halist(struct ha_interface *i, int max, struct iovec *iov)
-+static int dhaad_get_halist(struct ha_interface *i, uint16_t flags,
-+ int max, struct iovec *iov)
- {
- struct list_head *lp;
- int n = 0;
- list_for_each(lp, &i->ha_list) {
- struct home_agent *h;
- h = list_entry(lp, struct home_agent, list);
-- n++;
-- iov[n].iov_len = sizeof(struct in6_addr);
-- iov[n].iov_base = &h->addr;
-- if (n >= max)
-- break;
-+ if (!(flags & MIP_DHREQ_FLAG_SUPPORT_MR) ||
-+ h->flags & ND_OPT_HAI_FLAG_SUPPORT_MR) {
-+ n++;
-+ iov[n].iov_len = sizeof(struct in6_addr);
-+ iov[n].iov_base = &h->addr;
-+ if (n >= max)
-+ break;
-+ }
- }
- return n;
- }
-@@ -177,8 +182,12 @@ static void dhaad_recv_req(const struct
-
- rph->mip_dhrep_id = rqh->mip_dhreq_id;
-
-+ if (rqh->mip_dhreq_flags_reserved & MIP_DHREQ_FLAG_SUPPORT_MR)
-+ rph->mip_dhrep_flags_reserved = MIP_DHREP_FLAG_SUPPORT_MR;
-+
- pthread_rwlock_rdlock(&ha_lock);
-- iovlen = dhaad_get_halist(i, MAX_HOME_AGENTS, iov);
-+ iovlen = dhaad_get_halist(i, rqh->mip_dhreq_flags_reserved,
-+ MAX_HOME_AGENTS, iov);
- icmp6_send(i->ifindex, 64, ha_addr, src, iov, iovlen + 1);
- pthread_rwlock_unlock(&ha_lock);
- free_iov_data(&iov[0], 1);
-diff -r a7e20b0b5c43 src/dhaad_ha.h
---- a/src/dhaad_ha.h Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/dhaad_ha.h Tue Jan 08 11:28:48 2008 +0100
-@@ -17,8 +17,8 @@ void dhaad_halist_iterate(struct ha_inte
- int (* func)(int, void *, void *), void *arg);
- #endif
-
--void dhaad_insert_halist(struct ha_interface *i,
-- uint16_t key, uint16_t life_sec,
-+void dhaad_insert_halist(struct ha_interface *i, uint16_t key,
-+ uint16_t life_sec, uint16_t flags,
- struct nd_opt_prefix_info *pinfo,
- const struct in6_addr *lladdr);
-
-diff -r a7e20b0b5c43 src/dhaad_mn.c
---- a/src/dhaad_mn.c Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/dhaad_mn.c Tue Jan 08 11:28:48 2008 +0100
-@@ -86,7 +86,8 @@ static int dhaad_append_candidate(struct
- }
-
- static int dhaad_send_request(int oif, struct in6_addr *src,
-- struct in6_addr *pfx, int plen)
-+ struct in6_addr *pfx, int plen,
-+ uint16_t flags)
- {
- struct mip_dhaad_req *ih;
- struct iovec iov;
-@@ -98,6 +99,7 @@ static int dhaad_send_request(int oif, s
- return -1;
- id = dhaad_id++;
- ih->mip_dhreq_id = htons(id);
-+ ih->mip_dhreq_flags_reserved = flags;
- dhaad_gen_ha_anycast(&dst, pfx, plen);
- icmp6_send(oif, 0, src, &dst, &iov, 1);
- free_iov_data(&iov, 1);
-@@ -121,7 +123,9 @@ static void dhaad_resend(struct tq_elem
- t->dhaad_id = dhaad_send_request(hai->primary_coa.iif,
- &hai->primary_coa.addr,
- &hai->home_prefix,
-- hai->home_plen);
-+ hai->home_plen,
-+ hai->mob_rtr?
-+ MIP_DHREQ_FLAG_SUPPORT_MR:0);
- t->dhaad_resends++;
- tsadd(t->dhaad_delay, t->dhaad_delay, t->dhaad_delay);
- add_task_rel(&t->dhaad_delay, &t->tqe, dhaad_resend);
-@@ -139,11 +143,15 @@ static void _dhaad_start(struct home_add
- t->dhaad_resends == DHAAD_RETRIES))) {
- if (!(hai->home_block & HOME_ADDR_BLOCK))
- xfrm_block_hoa(hai);
-+ if (hai->mob_rtr && !(hai->home_block & NEMO_RA_BLOCK))
-+ xfrm_block_ra(hai);
- t->dhaad_resends = 0;
- t->dhaad_id = dhaad_send_request(hai->primary_coa.iif,
- &hai->primary_coa.addr,
- &hai->home_prefix,
-- hai->home_plen);
-+ hai->home_plen,
-+ hai->mob_rtr?
-+ MIP_DHREQ_FLAG_SUPPORT_MR:0);
- t->dhaad_delay = INITIAL_DHAAD_TIMEOUT_TS;
- add_task_rel(&t->dhaad_delay, &t->tqe, dhaad_resend);
- }
-@@ -165,6 +173,8 @@ static void _dhaad_stop(struct home_addr
- tsclear(t->dhaad_delay);
- if (hai->home_block & HOME_ADDR_BLOCK)
- xfrm_unblock_hoa(hai);
-+ if (hai->home_block & NEMO_RA_BLOCK)
-+ xfrm_unblock_ra(hai);
- }
-
- void dhaad_stop(struct home_addr_info *hai)
-@@ -245,6 +255,12 @@ static void dhaad_recv_rep(const struct
- pthread_rwlock_unlock(&mn_lock);
- return;
- }
-+ if (hai->mob_rtr &&
-+ !(rph->mip_dhrep_flags_reserved & MIP_DHREP_FLAG_SUPPORT_MR)) {
-+ dbg("HA doesn't support MR\n");
-+ pthread_rwlock_unlock(&mn_lock);
-+ return;
-+ }
- ha = (struct in6_addr *)(ih + 1);
-
- dhaad_flush_candidates(&hai->ha_list);
-diff -r a7e20b0b5c43 src/gram.y
---- a/src/gram.y Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/gram.y Tue Jan 08 11:28:48 2008 +0100
-@@ -30,10 +30,10 @@
- #ifdef HAVE_CONFIG_H
- #include
- #endif
-+#include
- #include
- #include
- #include
--#include
- #include
- #include
- #include
-@@ -54,8 +54,23 @@ struct net_iface ni = {
- };
-
- struct home_addr_info hai = {
-- .ro_policies = LIST_HEAD_INIT(hai.ro_policies)
-+ .ro_policies = LIST_HEAD_INIT(hai.ro_policies),
-+ .mob_net_prefixes = LIST_HEAD_INIT(hai.mob_net_prefixes)
- };
-+
-+LIST_HEAD(prefixes);
-+
-+int mv_prefixes(struct list_head *list)
-+{
-+ struct list_head *l, *n;
-+ int res = 0;
-+ list_for_each_safe(l, n, &prefixes) {
-+ list_del(l);
-+ list_add_tail(l, list);
-+ res++;
-+ }
-+ return res;
-+}
-
- struct policy_bind_acl_entry *bae = NULL;
-
-@@ -165,6 +180,11 @@ static void uerror(const char *fmt, ...)
- %token MNROUTERPROBETIMEOUT
- %token MNDISCARDHAPARAMPROB
- %token OPTIMISTICHANDOFF
-+%token HOMEPREFIX
-+%token HAACCEPTMOBRTR
-+%token ISMOBRTR
-+%token HASERVEDPREFIX
-+%token MOBRTRUSEEXPLICITMODE
-
- %token INV_TOKEN
-
-@@ -282,6 +302,19 @@ topdef : MIP6ENTITY mip6entity ';'
- {
- conf.DefaultBindingAclPolicy = $2;
- }
-+ | HAACCEPTMOBRTR BOOL ';'
-+ {
-+ conf.HaAcceptMobRtr = $2;
-+ }
-+ | HASERVEDPREFIX prefixlistentry ';'
-+ {
-+ list_splice(&prefixes,
-+ conf.nemo_ha_served_prefixes.prev);
-+ }
-+ | MOBRTRUSEEXPLICITMODE BOOL ';'
-+ {
-+ conf.MobRtrUseExplicitMode = $2;
-+ }
- | BINDINGACLPOLICY bindaclpolicy ';'
- {
- bae = NULL;
-@@ -398,12 +431,16 @@ linksub : QSTRING '{' linkdefs '}'
- memcpy(nhai, &hai, sizeof(struct home_addr_info));
- INIT_LIST_HEAD(&nhai->ro_policies);
- INIT_LIST_HEAD(&nhai->ha_list.home_agents);
-+ INIT_LIST_HEAD(&nhai->mob_net_prefixes);
- nhai->ha_list.dhaad_id = -1;
- list_splice(&hai.ro_policies, &nhai->ro_policies);
-+ list_splice(&hai.mob_net_prefixes,
-+ &nhai->mob_net_prefixes);
- list_add_tail(&nhai->list, &conf.home_addrs);
-
- memset(&hai, 0, sizeof(struct home_addr_info));
- INIT_LIST_HEAD(&hai.ro_policies);
-+ INIT_LIST_HEAD(&hai.mob_net_prefixes);
- }
- ;
-
-@@ -415,16 +452,35 @@ linkdef : HOMEAGENTADDRESS ADDR ';'
- {
- memcpy(&hai.ha_addr, &$2, sizeof(struct in6_addr));
- }
-- | HOMEADDRESS ADDR '/' prefixlen ';'
-- {
-- hai.hoa.addr = $2;
-- hai.plen = $4;
-- }
-+ | HOMEADDRESS homeaddress ';'
- | USEALTCOA BOOL ';'
- {
- hai.altcoa = $2;
- }
- | MNROPOLICY mnropolicy ';'
-+ | ISMOBRTR BOOL ';'
-+ {
-+ if ($2)
-+ hai.mob_rtr = IP6_MH_BU_MR;
-+ }
-+ | HOMEPREFIX ADDR '/' prefixlen ';'
-+ {
-+ ipv6_addr_prefix(&hai.home_prefix, &$2, $4);
-+ hai.home_plen = $4;
-+ }
-+ ;
-+
-+homeaddress : homeaddrdef prefixlistsub
-+ {
-+ hai.mnp_count = mv_prefixes(&hai.mob_net_prefixes);
-+ }
-+ ;
-+
-+homeaddrdef : ADDR '/' prefixlen
-+ {
-+ hai.hoa.addr = $1;
-+ hai.plen = $3;
-+ }
- ;
-
- ipsecpolicyset : ipsechaaddrdef ipsecmnaddrdefs ipsecpolicydefs
-@@ -639,7 +695,7 @@ bindaclpolval : BOOL
- | NUMBER { $$ = $1; }
- ;
-
--bindaclpolicy : ADDR bindaclpolval
-+bindaclpolicy : ADDR prefixlistsub bindaclpolval
- {
- bae = malloc(sizeof(struct policy_bind_acl_entry));
- if (bae == NULL) {
-@@ -649,7 +705,9 @@ bindaclpolicy : ADDR bindaclpolval
- memset(bae, 0, sizeof(struct policy_bind_acl_entry));
- bae->hoa = $1;
- bae->plen = 128;
-- bae->bind_policy = $2;
-+ INIT_LIST_HEAD(&bae->mob_net_prefixes);
-+ bae->mnp_count = mv_prefixes(&bae->mob_net_prefixes);
-+ bae->bind_policy = $3;
- list_add_tail(&bae->list, &conf.bind_acl);
- }
- ;
-@@ -664,4 +722,27 @@ prefixlen : NUMBER
- }
- ;
-
-+prefixlistsub :
-+ | '(' prefixlist ')'
-+ ;
-+
-+prefixlist : prefixlistentry
-+ | prefixlist ',' prefixlistentry
-+ ;
-+
-+prefixlistentry : ADDR '/' prefixlen
-+ {
-+ struct prefix_list_entry *p;
-+ p = malloc(sizeof(struct prefix_list_entry));
-+ if (p == NULL) {
-+ fprintf(stderr,
-+ "%s: out of memory\n", __FUNCTION__);
-+ return -1;
-+ }
-+ memset(p, 0, sizeof(struct prefix_list_entry));
-+ p->ple_prefix = $1;
-+ p->ple_plen = $3;
-+ list_add_tail(&p->list, &prefixes);
-+ }
-+ ;
- %%
-diff -r a7e20b0b5c43 src/ha.c
---- a/src/ha.c Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/ha.c Tue Jan 08 11:28:48 2008 +0100
-@@ -79,6 +79,7 @@ static void ha_recv_ra(const struct icmp
- struct ha_interface *iface;
- uint16_t pref = 0;
- uint16_t life = 0;
-+ uint16_t flags = 0;
-
- /* validity checks */
- if (hoplimit < 255 || !IN6_IS_ADDR_LINKLOCAL(src) ||
-@@ -120,6 +121,7 @@ static void ha_recv_ra(const struct icmp
- hainfo = (struct nd_opt_homeagent_info *)opt;
- pref = ntohs(hainfo->nd_opt_hai_preference);
- life = ntohs(hainfo->nd_opt_hai_lifetime);
-+ flags = hainfo->nd_opt_hai_flags_reserved;
- }
- optlen -= olen;
- opt += olen;
-@@ -129,7 +131,7 @@ static void ha_recv_ra(const struct icmp
- if (pinfo[i]->nd_opt_pi_flags_reserved &
- ND_OPT_PI_FLAG_RADDR) {
- dhaad_insert_halist(iface, pref, life,
-- pinfo[i], src);
-+ flags, pinfo[i], src);
- }
- }
- mpd_del_expired_pinfos(iface);
-@@ -499,14 +501,53 @@ static int ha_vt_init(void)
- }
- #endif
-
-+
-+static void nemo_ha_del_mnp_routes(struct list_head *old_mnps,
-+ struct list_head *new_mnps,
-+ int ifindex, int all)
-+{
-+ struct list_head *list;
-+ list_for_each(list, old_mnps) {
-+ struct prefix_list_entry *p;
-+ p = list_entry(list, struct prefix_list_entry, list);
-+ if (!all &&
-+ prefix_list_find(new_mnps, &p->ple_prefix, p->ple_plen))
-+ continue;
-+
-+ route_del(ifindex, RT6_TABLE_MIP6, IP6_RT_PRIO_MIP6_FWD,
-+ NULL, 0, &p->ple_prefix, p->ple_plen, NULL);
-+ }
-+}
-+
-+static int nemo_ha_add_mnp_routes(struct list_head *old_mnps,
-+ struct list_head *new_mnps,
-+ int ifindex, int all)
-+{
-+ struct list_head *list;
-+ list_for_each(list, new_mnps) {
-+ struct prefix_list_entry *p;
-+ p = list_entry(list, struct prefix_list_entry, list);
-+ if (!all &&
-+ prefix_list_find(old_mnps, &p->ple_prefix, p->ple_plen))
-+ continue;
-+ if (route_add(ifindex, RT6_TABLE_MIP6, RTPROT_MIP,
-+ 0, IP6_RT_PRIO_MIP6_FWD,
-+ NULL, 0, &p->ple_prefix, p->ple_plen, NULL) < 0)
-+ return -1;
-+ }
-+ return 0;
-+}
-+
- struct home_tnl_ops_parm {
- struct bcentry *bce;
- int ba_status;
-+ struct list_head mob_net_prefixes;
- };
-
- static int home_tnl_del(int old_if, int new_if, struct home_tnl_ops_parm *p)
- {
- const struct in6_addr *our_addr, *peer_addr, *coa, *old_coa;
-+ struct list_head *mnp;
-
- assert(old_if);
-
-@@ -514,17 +555,22 @@ static int home_tnl_del(int old_if, int
- peer_addr = &p->bce->peer_addr;
- coa = &p->bce->peer_addr;
- old_coa = &p->bce->coa;
-+ mnp = &p->bce->mob_net_prefixes;
-
- if (conf.UseMnHaIPsec) {
- /* migrate */
- ha_ipsec_tnl_update(our_addr, peer_addr,
-- coa, old_coa, p->bce->tunnel);
-+ coa, old_coa, p->bce->tunnel, mnp);
- /* delete SP entry */
-- ha_ipsec_tnl_pol_del(our_addr, peer_addr, p->bce->tunnel);
-+ ha_ipsec_tnl_pol_del(our_addr, peer_addr, p->bce->tunnel, mnp);
- }
- /* delete HoA route */
- route_del(old_if, RT6_TABLE_MAIN,
- IP6_RT_PRIO_MIP6_FWD, NULL, 0, peer_addr, 128, NULL);
-+
-+ /* delete MNP routes */
-+ nemo_ha_del_mnp_routes(&p->bce->mob_net_prefixes,
-+ &p->mob_net_prefixes, old_if, 1);
- /* update tunnel interface */
- p->bce->tunnel = new_if;
-
-@@ -534,17 +580,29 @@ static int home_tnl_add(int old_if, int
- static int home_tnl_add(int old_if, int new_if, struct home_tnl_ops_parm *p)
- {
- const struct in6_addr *our_addr, *peer_addr, *coa, *old_coa;
-+ struct list_head *mnp;
-
- assert(new_if);
-
- our_addr = &p->bce->our_addr;
- peer_addr = &p->bce->peer_addr;
- coa = &p->bce->coa;
-- old_coa = &p->bce->peer_addr;
-+ old_coa = IN6_ARE_ADDR_EQUAL(&p->bce->old_coa, &in6addr_any) ?
-+ &p->bce->peer_addr : &p->bce->old_coa;
-+ mnp = &p->mob_net_prefixes;
-
- /* update tunnel interface */
- p->bce->tunnel = new_if;
-
-+ /* add MNP routes */
-+ if (nemo_ha_add_mnp_routes(&p->bce->mob_net_prefixes,
-+ &p->mob_net_prefixes, new_if, 1) < 0) {
-+ if (p->bce->nemo_type == BCE_NEMO_EXPLICIT)
-+ p->ba_status = IP6_MH_BAS_INVAL_PRFX;
-+ else
-+ p->ba_status = IP6_MH_BAS_FWDING_FAILED;
-+ goto err;
-+ }
- /* add HoA route */
- if (route_add(new_if, RT6_TABLE_MAIN,
- RTPROT_MIP, 0, IP6_RT_PRIO_MIP6_FWD,
-@@ -555,13 +613,13 @@ static int home_tnl_add(int old_if, int
- /* add SP entry */
- if (conf.UseMnHaIPsec) {
- if (ha_ipsec_tnl_pol_add(our_addr, peer_addr,
-- p->bce->tunnel) < 0) {
-+ p->bce->tunnel, mnp) < 0) {
- p->ba_status = IP6_MH_BAS_INSUFFICIENT;
- goto err;
- }
- /* migrate */
- if (ha_ipsec_tnl_update(our_addr, peer_addr, coa, old_coa,
-- p->bce->tunnel) < 0) {
-+ p->bce->tunnel, mnp) < 0) {
- p->ba_status = IP6_MH_BAS_INSUFFICIENT;
- goto err;
- }
-@@ -578,17 +636,51 @@ static int home_tnl_chg(int old_if, int
-
- if (old_if == new_if) {
- const struct in6_addr *our_addr, *peer_addr, *coa, *old_coa;
-+ struct list_head *mnp;
-
- our_addr = &p->bce->our_addr;
- peer_addr = &p->bce->peer_addr;
- coa = &p->bce->coa;
- old_coa = &p->bce->old_coa;
-+ mnp = &p->mob_net_prefixes;
-+
-+ /* if interface hasn't changed, at least check if the
-+ MR's MNPs have changed */
-+ if (!prefix_list_cmp(&p->bce->mob_net_prefixes,
-+ &p->mob_net_prefixes)) {
-+
-+ /* Remove old policies and install new ones */
-+ if (conf.UseMnHaIPsec) {
-+ ha_ipsec_mnp_pol_del(our_addr, peer_addr,
-+ &p->bce->mob_net_prefixes,
-+ &p->mob_net_prefixes,
-+ p->bce->tunnel);
-+ ha_ipsec_mnp_pol_add(our_addr, peer_addr,
-+ &p->bce->mob_net_prefixes,
-+ &p->mob_net_prefixes,
-+ p->bce->tunnel);
-+ }
-+
-+ /* Do the same for routes */
-+ nemo_ha_del_mnp_routes(&p->bce->mob_net_prefixes,
-+ &p->mob_net_prefixes,
-+ old_if, 0);
-+ if (nemo_ha_add_mnp_routes(&p->bce->mob_net_prefixes,
-+ &p->mob_net_prefixes,
-+ new_if, 0) < 0) {
-+ if (p->bce->nemo_type == BCE_NEMO_EXPLICIT)
-+ p->ba_status = IP6_MH_BAS_INVAL_PRFX;
-+ else
-+ p->ba_status = IP6_MH_BAS_FWDING_FAILED;
-+ return -1;
-+ }
-+ }
-
- /* migrate */
- if (conf.UseMnHaIPsec &&
- !IN6_ARE_ADDR_EQUAL(old_coa, coa) &&
- ha_ipsec_tnl_update(our_addr, peer_addr, coa, old_coa,
-- p->bce->tunnel) < 0) {
-+ p->bce->tunnel, mnp) < 0) {
- return -1;
- }
- } else {
-@@ -632,6 +724,61 @@ static void home_cleanup(struct bcentry
- if (conf.UseMnHaIPsec) {
- ha_mn_ipsec_pol_mod(&bce->our_addr, &bce->peer_addr);
- }
-+}
-+
-+
-+static int ha_extract_mnps(const struct ip6_mh_binding_update *bu,
-+ const struct mh_options *opts,
-+ struct list_head *mob_net_prefixes)
-+{
-+ struct ip6_mh_opt_mob_net_prefix *op;
-+ int prefix_count = 0;
-+ for (op = mh_opt(&bu->ip6mhbu_hdr, opts, IP6_MHOPT_MOB_NET_PRFX);
-+ op != NULL;
-+ op = mh_opt_next(&bu->ip6mhbu_hdr, opts, op)) {
-+ struct prefix_list_entry *p;
-+ p = malloc(sizeof(struct prefix_list_entry));
-+ if (p == NULL) {
-+ prefix_list_free(mob_net_prefixes);
-+ return -1;
-+ }
-+ memset(p, 0, sizeof(struct prefix_list_entry));
-+ p->ple_plen = op->ip6mnp_prefix_len;
-+ p->ple_prefix = op->ip6mnp_prefix;
-+ list_add_tail(&p->list, mob_net_prefixes);
-+ prefix_count++;
-+ }
-+ return prefix_count;
-+}
-+
-+static int ha_get_mnps(const struct in6_addr *hoa,
-+ struct list_head *mob_net_prefixes)
-+{
-+ struct nd_opt_prefix_info *mnps;
-+ int mnp_count = conf.pmgr.get_mnp_count(hoa);
-+ int i;
-+
-+ if (mnp_count <= 0)
-+ return mnp_count;
-+
-+ mnps = calloc(mnp_count, sizeof(struct nd_opt_prefix_info));
-+ if (mnps == NULL)
-+ return -1;
-+
-+ mnp_count = conf.pmgr.get_mnps(hoa, mnp_count, mnps);
-+ for (i = 0; i < mnp_count; i++) {
-+ struct prefix_list_entry *p;
-+ p = malloc(sizeof(struct prefix_list_entry));
-+ if (p == NULL) {
-+ prefix_list_free(mob_net_prefixes);
-+ free(mnps);
-+ return -1;
-+ }
-+ p->pinfo = *(mnps + i);
-+ list_add_tail(&p->list, mob_net_prefixes);
-+ }
-+ free(mnps);
-+ return mnp_count;
- }
-
- struct ha_recv_bu_args {
-@@ -684,8 +831,9 @@ restart:
- bce = bcache_get(out.src, out.dst);
- if (bce) {
- if (bce->type != BCE_NONCE_BLOCK) {
-- if (!(bce->flags & IP6_MH_BU_HOME)) {
-- /* H-bit mismatch, flags changed */
-+ /* H-bit or R-bit mismatch, flags changed */
-+ if ((bce->flags ^ bu_flags) &
-+ (IP6_MH_BU_HOME | IP6_MH_BU_MR)) {
- bcache_release_entry(bce);
- bce = NULL;
- status = IP6_MH_BAS_REG_NOT_ALLOWED;
-@@ -733,9 +881,15 @@ restart:
- }
- if ((status = mpd_prefix_check(out.src, out.dst,
- &lft, &home_ifindex, new)) < 0) {
-- /* not home agent for this subnet */
-- status = IP6_MH_BAS_NOT_HOME_SUBNET;
-- goto send_nack;
-+ if (!(bu_flags & IP6_MH_BU_MR) ||
-+ home_ifindex == 0 ||
-+ !prefix_list_find(&conf.nemo_ha_served_prefixes,
-+ out.dst, 0)) {
-+ /* not home agent for this subnet */
-+ status = IP6_MH_BAS_NOT_HOME_SUBNET;
-+ goto send_nack;
-+ }
-+ status = IP6_MH_BAS_ACCEPTED;
- }
- status = conf.pmgr.discard_binding(out.dst, out.bind_coa,
- out.src, arg->bu, arg->len);
-@@ -787,6 +941,25 @@ restart:
- }
- new = 1;
- }
-+ INIT_LIST_HEAD(&p.mob_net_prefixes);
-+ if (bu_flags & IP6_MH_BU_MR && tsisset(lft)) {
-+ if (mh_opt(&arg->bu->ip6mhbu_hdr,
-+ &arg->mh_opts, IP6_MHOPT_MOB_NET_PRFX) != NULL) {
-+ if (ha_extract_mnps(arg->bu,
-+ &arg->mh_opts,
-+ &p.mob_net_prefixes) < 0) {
-+ status = IP6_MH_BAS_INVAL_PRFX;
-+ goto send_nack;
-+ }
-+ bce->nemo_type = BCE_NEMO_EXPLICIT;
-+ } else if (ha_get_mnps(out.dst, &p.mob_net_prefixes) > 0) {
-+ bce->nemo_type = BCE_NEMO_IMPLICIT;
-+ } else {
-+ /* Todo: dynamic routing */
-+ status = IP6_MH_BAS_FWDING_FAILED;
-+ goto send_nack;
-+ }
-+ }
- p.bce = bce;
- p.ba_status = status;
- bce->seqno = seqno;
-@@ -801,6 +974,9 @@ restart:
- status = IP6_MH_BAS_INSUFFICIENT;
- goto send_nack;
- }
-+ /* Now save the MNP list in the BCE */
-+ list_splice(&p.mob_net_prefixes, &bce->mob_net_prefixes);
-+
- bce->cleanup = home_cleanup;
-
- if (route_add(bce->link, RT6_TABLE_MIP6,
-@@ -829,6 +1005,10 @@ restart:
- status = IP6_MH_BAS_INSUFFICIENT;
- goto send_nack;
- }
-+ /* Now update the MNP list in the BCE */
-+ prefix_list_free(&bce->mob_net_prefixes);
-+ list_splice(&p.mob_net_prefixes, &bce->mob_net_prefixes);
-+
- bcache_update_expire(bce);
- }
- /* bce is always valid here */
-@@ -855,6 +1035,9 @@ restart:
- * have a binding before sending this Binding Update,
- * discard the connections to the home address. */
- }
-+ if (status < IP6_MH_BAS_UNSPECIFIED && bu_flags & IP6_MH_BU_MR)
-+ ba_flags |= IP6_MH_BA_MR;
-+
- if (!(arg->flags & HA_BU_F_SKIP_BA))
- mh_send_ba(&out, status, ba_flags, seqno, &lft, NULL, iif);
- if (new && tsisset(lft))
-diff -r a7e20b0b5c43 src/ha.h
---- a/src/ha.h Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/ha.h Tue Jan 08 11:28:48 2008 +0100
-@@ -23,6 +23,7 @@ struct home_agent {
- struct list_head list;
- struct in6_addr addr;
- uint16_t preference;
-+ uint16_t flags;
- struct timespec lifetime;
- struct ha_interface *iface;
- struct tq_elem tqe;
-diff -r a7e20b0b5c43 src/ipsec.c
---- a/src/ipsec.c Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/ipsec.c Tue Jan 08 11:28:48 2008 +0100
-@@ -81,7 +81,9 @@ static void _set_sp(struct xfrm_userpoli
- struct ipsec_policy_entry *e,
- int dir,
- const struct in6_addr *in6_dst,
-+ int dst_len,
- const struct in6_addr *in6_src,
-+ int src_len,
- int ifindex,
- int nodetype)
- {
-@@ -97,10 +99,13 @@ static void _set_sp(struct xfrm_userpoli
- sp->action = e->action;
- memcpy(&sp->sel.saddr.a6, in6_src, sizeof(sp->sel.saddr.a6));
- memcpy(&sp->sel.daddr.a6, in6_dst, sizeof(sp->sel.daddr.a6));
-- sp->sel.prefixlen_s = IN6_ARE_ADDR_EQUAL(in6_src, &in6addr_any) ?
-- 0 : 128;
-- sp->sel.prefixlen_d = IN6_ARE_ADDR_EQUAL(in6_dst, &in6addr_any) ?
-- 0 : 128;
-+ sp->sel.prefixlen_s = src_len;
-+ if (!src_len && (!IN6_ARE_ADDR_EQUAL(in6_src, &in6addr_any)))
-+ sp->sel.prefixlen_s = 128;
-+ sp->sel.prefixlen_d = dst_len;
-+ if (!dst_len && (!IN6_ARE_ADDR_EQUAL(in6_dst, &in6addr_any)))
-+ sp->sel.prefixlen_d = 128;
-+
- sp->sel.ifindex = 0;
-
- switch (e->type) {
-@@ -347,6 +352,7 @@ struct ha_ipsec_tnl_update {
- int tunnel;
- struct in6_addr coa;
- struct in6_addr old_coa;
-+ struct list_head *mnp;
- };
-
- /*
-@@ -365,6 +371,7 @@ static int _ha_tnl_update(const struct i
- int ifindex;
- const struct in6_addr *oldcoa, *newcoa;
- const struct in6_addr *peer_addr = hoa;
-+ struct list_head *mnp;
- u_int8_t ipsec_proto;
- struct xfrm_user_tmpl tmpl;
- struct xfrm_userpolicy_info sp;
-@@ -399,13 +406,14 @@ static int _ha_tnl_update(const struct i
- oldcoa = IN6_ARE_ADDR_EQUAL(&info->old_coa, &in6addr_any) ?
- peer_addr : &info->old_coa;
- newcoa = &info->coa;
-+ mnp = info->mnp;
-
- dump_migrate(ifindex, ipsec_proto, hoa, haaddr, oldcoa, newcoa);
-
- /* inbound */
- _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
- haaddr, oldcoa, e->reqid_toha);
-- _set_sp(&sp, e, XFRM_POLICY_IN, &in6addr_any, hoa,
-+ _set_sp(&sp, e, XFRM_POLICY_IN, &in6addr_any, 0, hoa, 0,
- ifindex, MIP6_ENTITY_HA);
- if ((err = xfrm_sendmigrate(&sp, &tmpl, haaddr, newcoa)) < 0) {
- dbg("migrate for INBOUND policy failed\n");
-@@ -415,7 +423,7 @@ static int _ha_tnl_update(const struct i
- /* forward */
- _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
- haaddr, oldcoa, e->reqid_toha);
-- _set_sp(&sp, e, XFRM_POLICY_FWD, &in6addr_any, hoa,
-+ _set_sp(&sp, e, XFRM_POLICY_FWD, &in6addr_any, 0, hoa, 0,
- ifindex, MIP6_ENTITY_HA);
- if ((err = xfrm_sendmigrate(&sp, &tmpl, haaddr, newcoa)) < 0) {
- dbg("migrate for FORWARD policy failed\n");
-@@ -425,11 +433,54 @@ static int _ha_tnl_update(const struct i
- /* outbound */
- _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
- oldcoa, haaddr, e->reqid_tomn);
-- _set_sp(&sp, e, XFRM_POLICY_OUT, hoa, &in6addr_any,
-+ _set_sp(&sp, e, XFRM_POLICY_OUT, hoa, 0, &in6addr_any, 0,
- ifindex, MIP6_ENTITY_HA);
- if ((err = xfrm_sendmigrate(&sp, &tmpl, newcoa, haaddr)) < 0) {
- dbg("migrate for OUTBOUND policy failed\n");
- goto end;
-+ }
-+
-+ /* Mobile router case */
-+ if ( (e->type == IPSEC_POLICY_TYPE_TUNNELPAYLOAD) && mnp)
-+ {
-+ struct list_head *list;
-+
-+ /* We have to modify rules to protect traffic to and from MNP's, the same way as HoA */
-+ list_for_each(list, mnp)
-+ {
-+ struct prefix_list_entry *p;
-+ p = list_entry(list, struct prefix_list_entry, list);
-+
-+ /* inbound */
-+ _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
-+ haaddr, oldcoa, e->reqid_toha);
-+ _set_sp(&sp, e, XFRM_POLICY_IN, &in6addr_any, 0, &p->ple_prefix, p->ple_plen,
-+ ifindex, MIP6_ENTITY_HA);
-+ if ((err = xfrm_sendmigrate(&sp, &tmpl, haaddr, newcoa)) < 0) {
-+ dbg("migrate for INBOUND policy failed\n");
-+ goto end;
-+ }
-+
-+ /* forward */
-+ _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
-+ haaddr, oldcoa, e->reqid_toha);
-+ _set_sp(&sp, e, XFRM_POLICY_FWD, &in6addr_any, 0, &p->ple_prefix, p->ple_plen,
-+ ifindex, MIP6_ENTITY_HA);
-+ if ((err = xfrm_sendmigrate(&sp, &tmpl, haaddr, newcoa)) < 0) {
-+ dbg("migrate for FORWARD policy failed\n");
-+ goto end;
-+ }
-+
-+ /* outbound */
-+ _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
-+ oldcoa, haaddr, e->reqid_tomn);
-+ _set_sp(&sp, e, XFRM_POLICY_OUT, &p->ple_prefix, p->ple_plen, &in6addr_any, 0,
-+ ifindex, MIP6_ENTITY_HA);
-+ if ((err = xfrm_sendmigrate(&sp, &tmpl, newcoa, haaddr)) < 0) {
-+ dbg("migrate for OUTBOUND policy failed\n");
-+ goto end;
-+ }
-+ }
- }
-
- end:
-@@ -440,13 +491,176 @@ int ha_ipsec_tnl_update(const struct in6
- const struct in6_addr *hoa,
- const struct in6_addr *coa,
- const struct in6_addr *old_coa,
-- int tunnel)
-+ int tunnel,
-+ struct list_head *mnp)
- {
- struct ha_ipsec_tnl_update b;
- b.coa = *coa;
- b.old_coa = *old_coa;
- b.tunnel = tunnel;
-+ b.mnp = mnp;
- return ipsec_policy_apply(haaddr, hoa, _ha_tnl_update, &b);
-+}
-+
-+struct ha_ipsec_mnp_update {
-+ int tunnel;
-+ struct list_head *old_mnps;
-+ struct list_head *new_mnps;
-+};
-+
-+/*
-+ * Add/Delete MNP IPsec Security Policy
-+ */
-+static int _ha_mnp_pol_mod(const struct in6_addr *haaddr,
-+ const struct in6_addr *hoa,
-+ struct ipsec_policy_entry *e,
-+ void *arg,
-+ int add)
-+{
-+ int err = 0;
-+ struct ha_ipsec_mnp_update *parms = (struct ha_ipsec_mnp_update *)arg;
-+ struct xfrm_userpolicy_info sp;
-+ struct xfrm_user_tmpl tmpl;
-+ u_int16_t ipsec_proto;
-+ struct list_head *list, *old_mnps, *new_mnps, *main_mnps, *ref_mnps;
-+ int ifindex;
-+
-+ assert(haaddr);
-+ assert(hoa);
-+ assert(e);
-+ assert(arg);
-+
-+ ifindex = parms->tunnel;
-+ old_mnps = parms->old_mnps;
-+ new_mnps = parms->new_mnps;
-+
-+ if (e->type != IPSEC_POLICY_TYPE_TUNNELPAYLOAD)
-+ goto end;
-+
-+ /* XXX Limitation: Single IPsec proto can only be applied */
-+ if (ipsec_use_esp(e))
-+ ipsec_proto = IPPROTO_ESP;
-+ else if (ipsec_use_ah(e))
-+ ipsec_proto = IPPROTO_AH;
-+ else if (ipsec_use_ipcomp(e))
-+ ipsec_proto = IPPROTO_COMP;
-+ else {
-+ dbg("invalid ipsec proto\n");
-+ goto end;
-+ }
-+
-+ /* Reverse the search logic on lists based on expected
-+ * action (add/del) */
-+ main_mnps = add ? new_mnps : old_mnps;
-+ ref_mnps = add ? old_mnps : new_mnps;
-+
-+ if (main_mnps == NULL)
-+ goto end;
-+
-+ /* We have to add/delete rules to protect traffic to
-+ and from MNP's, the same way as HoA */
-+ list_for_each(list, main_mnps) {
-+ struct prefix_list_entry *p;
-+ p = list_entry(list, struct prefix_list_entry, list);
-+
-+ if (ref_mnps &&
-+ prefix_list_find(ref_mnps, &p->ple_prefix, p->ple_plen))
-+ continue;
-+
-+ /* inbound */
-+ _set_sp(&sp, e, XFRM_POLICY_IN, &in6addr_any, 0, &p->ple_prefix, p->ple_plen,
-+ ifindex, MIP6_ENTITY_HA);
-+ _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
-+ haaddr, hoa, e->reqid_toha);
-+ if (xfrm_ipsec_policy_mod(&sp, &tmpl, 1, add) < 0) {
-+ dbg("modifying INBOUND policy failed\n");
-+ err = -1;
-+ goto end;
-+ }
-+
-+ /* forward */
-+ _set_sp(&sp, e, XFRM_POLICY_FWD, &in6addr_any, 0, &p->ple_prefix, p->ple_plen,
-+ ifindex, MIP6_ENTITY_HA);
-+ _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
-+ haaddr, hoa, e->reqid_toha);
-+ if (xfrm_ipsec_policy_mod(&sp, &tmpl, 1, add) < 0) {
-+ dbg("modifying FORWARD policy failed\n");
-+ err = -1;
-+ goto end;
-+ }
-+
-+ /* outbound */
-+ _set_sp(&sp, e, XFRM_POLICY_OUT, &p->ple_prefix, p->ple_plen, &in6addr_any, 0,
-+ ifindex, MIP6_ENTITY_HA);
-+ _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
-+ hoa, haaddr, e->reqid_tomn);
-+ if (xfrm_ipsec_policy_mod(&sp, &tmpl, 1, add) < 0) {
-+ dbg("modifying OUTBOUND policy failed\n");
-+ err = -1;
-+ goto end;
-+ }
-+ }
-+
-+ end:
-+ return err;
-+}
-+
-+
-+/*
-+ * Add SP entry (for MNP on HA)
-+ *
-+ * NOTE:
-+ * - This is a hook routine to ipsec_policy_apply()
-+ */
-+static int _ha_mnp_pol_add(const struct in6_addr *haaddr,
-+ const struct in6_addr *hoa,
-+ struct ipsec_policy_entry *e,
-+ void *arg)
-+{
-+ return _ha_mnp_pol_mod(haaddr, hoa, e, arg, 1);
-+}
-+
-+int ha_ipsec_mnp_pol_add(const struct in6_addr *our_addr,
-+ const struct in6_addr *peer_addr,
-+ struct list_head *old_mnps,
-+ struct list_head *new_mnps,
-+ int tunnel)
-+{
-+ struct ha_ipsec_mnp_update b;
-+ b.tunnel = tunnel;
-+ b.old_mnps = old_mnps;
-+ b.new_mnps = new_mnps;
-+
-+ return ipsec_policy_apply(our_addr, peer_addr, _ha_mnp_pol_add, &b);
-+}
-+
-+/*
-+ * Delete SP entry (for MNP on HA)
-+ *
-+ * NOTE:
-+ * - This is a hook routine to ipsec_policy_apply()
-+ */
-+static int _ha_mnp_pol_del(const struct in6_addr *haaddr,
-+ const struct in6_addr *hoa,
-+ struct ipsec_policy_entry *e,
-+ void *arg)
-+{
-+ return _ha_mnp_pol_mod(haaddr, hoa, e, arg, 0);
-+}
-+
-+int ha_ipsec_mnp_pol_del(const struct in6_addr *our_addr,
-+ const struct in6_addr *peer_addr,
-+ struct list_head *old_mnps,
-+ struct list_head *new_mnps,
-+ int tunnel)
-+{
-+ struct ha_ipsec_mnp_update b;
-+ b.tunnel = tunnel;
-+ b.old_mnps = old_mnps;
-+ b.new_mnps = new_mnps;
-+
-+ return ipsec_policy_apply(our_addr, peer_addr,
-+ _ha_mnp_pol_del, &b);
- }
-
- /*
-@@ -459,7 +673,9 @@ static int _ha_tnl_pol_mod(const struct
- int add)
- {
- int err = 0;
-- int ifindex = *(int *)arg;
-+ struct ha_ipsec_tnl_update *parms = (struct ha_ipsec_tnl_update *)arg;
-+ int ifindex;
-+ struct list_head *mnp;
- struct xfrm_userpolicy_info sp;
- struct xfrm_user_tmpl tmpl;
- u_int16_t ipsec_proto;
-@@ -468,6 +684,9 @@ static int _ha_tnl_pol_mod(const struct
- assert(hoa);
- assert(e);
- assert(arg);
-+
-+ ifindex = parms->tunnel;
-+ mnp = parms->mnp;
-
- switch (e->type) {
- case IPSEC_POLICY_TYPE_TUNNELHOMETESTING:
-@@ -493,7 +712,7 @@ static int _ha_tnl_pol_mod(const struct
- dump_migrate(ifindex, ipsec_proto, hoa, haaddr, NULL, NULL);
-
- /* inbound */
-- _set_sp(&sp, e, XFRM_POLICY_IN, &in6addr_any, hoa,
-+ _set_sp(&sp, e, XFRM_POLICY_IN, &in6addr_any, 0, hoa, 0,
- ifindex, MIP6_ENTITY_HA);
- _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
- haaddr, hoa, e->reqid_toha);
-@@ -504,7 +723,7 @@ static int _ha_tnl_pol_mod(const struct
- }
-
- /* forward */
-- _set_sp(&sp, e, XFRM_POLICY_FWD, &in6addr_any, hoa,
-+ _set_sp(&sp, e, XFRM_POLICY_FWD, &in6addr_any, 0, hoa, 0,
- ifindex, MIP6_ENTITY_HA);
- _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
- haaddr, hoa, e->reqid_toha);
-@@ -515,7 +734,7 @@ static int _ha_tnl_pol_mod(const struct
- }
-
- /* outbound */
-- _set_sp(&sp, e, XFRM_POLICY_OUT, hoa, &in6addr_any,
-+ _set_sp(&sp, e, XFRM_POLICY_OUT, hoa, 0, &in6addr_any, 0,
- ifindex, MIP6_ENTITY_HA);
- _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
- hoa, haaddr, e->reqid_tomn);
-@@ -525,6 +744,16 @@ static int _ha_tnl_pol_mod(const struct
- goto end;
- }
-
-+ /* Mobile Router case */
-+ if ((e->type == IPSEC_POLICY_TYPE_TUNNELPAYLOAD) && mnp) {
-+ struct ha_ipsec_mnp_update b;
-+
-+ b.tunnel = ifindex;
-+ b.old_mnps = add ? NULL : mnp;
-+ b.new_mnps = add ? mnp : NULL;
-+
-+ err = _ha_mnp_pol_mod(haaddr, hoa, e, (void *)&b, add);
-+ }
- end:
- return err;
- }
-@@ -545,11 +774,14 @@ static int _ha_tnl_pol_add(const struct
-
- int ha_ipsec_tnl_pol_add(const struct in6_addr *our_addr,
- const struct in6_addr *peer_addr,
-- int tunnel)
-+ int tunnel,
-+ struct list_head *mnp)
- {
-- int t = tunnel;
-+ struct ha_ipsec_tnl_update b;
-+ b.tunnel = tunnel;
-+ b.mnp = mnp;
-
-- return ipsec_policy_apply(our_addr, peer_addr, _ha_tnl_pol_add, &t);
-+ return ipsec_policy_apply(our_addr, peer_addr, _ha_tnl_pol_add, &b);
- }
-
- /*
-@@ -568,12 +800,15 @@ static int _ha_tnl_pol_del(const struct
-
- int ha_ipsec_tnl_pol_del(const struct in6_addr *our_addr,
- const struct in6_addr *peer_addr,
-- int tunnel)
-+ int tunnel,
-+ struct list_head *mnp)
- {
-- int t = tunnel;
-+ struct ha_ipsec_tnl_update b;
-+ b.tunnel = tunnel;
-+ b.mnp = mnp;
-
- return ipsec_policy_apply(our_addr, peer_addr,
-- _ha_tnl_pol_del, &t);
-+ _ha_tnl_pol_del, &b);
- }
-
- /*
-@@ -631,7 +866,7 @@ static int _mn_tnl_update(const struct i
- /* outbound */
- _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
- haaddr, oldcoa, e->reqid_toha);
-- _set_sp(&sp, e, XFRM_POLICY_OUT, &in6addr_any, hoa,
-+ _set_sp(&sp, e, XFRM_POLICY_OUT, &in6addr_any, 0, hoa, 0,
- ifindex, MIP6_ENTITY_MN);
- if ((err = xfrm_sendmigrate(&sp, &tmpl, haaddr, newcoa)) < 0) {
- dbg("migrate for OUTBOUND policy failed\n");
-@@ -641,7 +876,7 @@ static int _mn_tnl_update(const struct i
- /* inbound */
- _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
- oldcoa, haaddr, e->reqid_tomn);
-- _set_sp(&sp, e, XFRM_POLICY_IN, hoa, &in6addr_any,
-+ _set_sp(&sp, e, XFRM_POLICY_IN, hoa, 0, &in6addr_any, 0,
- ifindex, MIP6_ENTITY_MN);
- if ((err = xfrm_sendmigrate(&sp, &tmpl, newcoa, haaddr)) < 0) {
- dbg("migrate for INBOUND policy (1) failed\n");
-@@ -657,7 +892,7 @@ static int _mn_tnl_update(const struct i
- /* template */
- _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
- oldcoa, haaddr, e->reqid_tomn);
-- _set_sp(&sp, e, XFRM_POLICY_IN, hoa, &in6addr_any,
-+ _set_sp(&sp, e, XFRM_POLICY_IN, hoa, 0, &in6addr_any, 0,
- ifindex, MIP6_ENTITY_MN);
- /* additional settings */
- sp.priority = MIP6_PRIO_RO_SIG_IPSEC;
-@@ -666,6 +901,52 @@ static int _mn_tnl_update(const struct i
- if ((err = xfrm_sendmigrate(&sp, &tmpl, newcoa, haaddr)) < 0) {
- dbg("migrate for INBOUND policy (2) failed\n");
- goto end;
-+ }
-+ }
-+
-+ /*
-+ * If we are a Mobile Router, we also need to migrate IN/FWD/OUT rules
-+ * for forwarded traffic in case we have TUNNELPAYLOAD protection.
-+ */
-+ if ((e->type == IPSEC_POLICY_TYPE_TUNNELPAYLOAD) && (bule->home->mob_rtr))
-+ {
-+ struct list_head *mnp;
-+
-+ list_for_each(mnp, &bule->home->mob_net_prefixes)
-+ {
-+ struct prefix_list_entry *p;
-+ p = list_entry(mnp, struct prefix_list_entry, list);
-+
-+ /* outbound */
-+ _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
-+ haaddr, oldcoa, e->reqid_toha);
-+ _set_sp(&sp, e, XFRM_POLICY_OUT, &in6addr_any, 0, &p->ple_prefix, p->ple_plen,
-+ ifindex, MIP6_ENTITY_MN);
-+ if ((err = xfrm_sendmigrate(&sp, &tmpl, haaddr, newcoa)) < 0) {
-+ dbg("migrate for OUTBOUND policy failed\n");
-+ goto end;
-+ }
-+
-+ /* forwarded */
-+ _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
-+ oldcoa, haaddr, e->reqid_tomn);
-+ _set_sp(&sp, e, XFRM_POLICY_IN, &p->ple_prefix, p->ple_plen, &in6addr_any, 0,
-+ ifindex, MIP6_ENTITY_MN);
-+ if ((err = xfrm_sendmigrate(&sp, &tmpl, newcoa, haaddr)) < 0) {
-+ dbg("migrate for INBOUND policy (1) failed\n");
-+ goto end;
-+ }
-+
-+ /* inbound */
-+ _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
-+ oldcoa, haaddr, e->reqid_tomn);
-+ _set_sp(&sp, e, XFRM_POLICY_IN, &p->ple_prefix, p->ple_plen, &in6addr_any, 0,
-+ ifindex, MIP6_ENTITY_MN);
-+ if ((err = xfrm_sendmigrate(&sp, &tmpl, newcoa, haaddr)) < 0) {
-+ dbg("migrate for INBOUND policy (1) failed\n");
-+ goto end;
-+ }
-+
- }
- }
-
-@@ -724,7 +1005,7 @@ static int _mn_tnl_pol_mod(const struct
- dump_migrate(ifindex, ipsec_proto, hoa, haaddr, NULL, NULL);
-
- /* inbound */
-- _set_sp(&sp, e, XFRM_POLICY_IN, hoa, &in6addr_any,
-+ _set_sp(&sp, e, XFRM_POLICY_IN, hoa, 0, &in6addr_any, 0,
- ifindex, MIP6_ENTITY_MN);
- _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
- hoa, haaddr, e->reqid_tomn);
-@@ -735,7 +1016,7 @@ static int _mn_tnl_pol_mod(const struct
- }
-
- /* outbound */
-- _set_sp(&sp, e, XFRM_POLICY_OUT, &in6addr_any, hoa,
-+ _set_sp(&sp, e, XFRM_POLICY_OUT, &in6addr_any, 0, hoa, 0,
- ifindex, MIP6_ENTITY_MN);
- _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
- haaddr, hoa, e->reqid_toha);
-@@ -758,6 +1039,54 @@ static int _mn_tnl_pol_mod(const struct
- mn_ipsec_recv_bu_tnl_pol_del(bule, ifindex, e);
- /* restore wildrecv SPD entry for processing BU */
- err = cn_wildrecv_bu_pol_add();
-+ }
-+ }
-+
-+ /*
-+ * If we are a Mobile Router, we also need to create IN/FWD/OUT rules
-+ * for forwarded traffic in case we have TUNNELPAYLOAD protection.
-+ */
-+ if ((e->type == IPSEC_POLICY_TYPE_TUNNELPAYLOAD) && (bule->home->mob_rtr))
-+ {
-+ struct list_head *mnp;
-+
-+ list_for_each(mnp, &bule->home->mob_net_prefixes)
-+ {
-+ struct prefix_list_entry *p;
-+ p = list_entry(mnp, struct prefix_list_entry, list);
-+
-+ /* inbound */
-+ _set_sp(&sp, e, XFRM_POLICY_IN, &p->ple_prefix, p->ple_plen, &in6addr_any, 0,
-+ ifindex, MIP6_ENTITY_MN);
-+ _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
-+ hoa, haaddr, e->reqid_tomn);
-+ if (xfrm_ipsec_policy_mod(&sp, &tmpl, 1, add) < 0) {
-+ dbg("modifying INBOUND policy failed.\n");
-+ err = -1;
-+ goto end;
-+ }
-+
-+ /* forward */
-+ _set_sp(&sp, e, XFRM_POLICY_FWD, &p->ple_prefix, p->ple_plen, &in6addr_any, 0,
-+ ifindex, MIP6_ENTITY_MN);
-+ _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
-+ hoa, haaddr, e->reqid_tomn);
-+ if (xfrm_ipsec_policy_mod(&sp, &tmpl, 1, add) < 0) {
-+ dbg("modifying INBOUND policy failed.\n");
-+ err = -1;
-+ goto end;
-+ }
-+
-+ /* outbound */
-+ _set_sp(&sp, e, XFRM_POLICY_OUT, &in6addr_any, 0, &p->ple_prefix, p->ple_plen,
-+ ifindex, MIP6_ENTITY_MN);
-+ _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
-+ haaddr, hoa, e->reqid_toha);
-+ if (xfrm_ipsec_policy_mod(&sp, &tmpl, 1, add) < 0) {
-+ dbg("modifying OUTBOUND policy failed.\n");
-+ err = -1;
-+ goto end;
-+ }
- }
- }
-
-diff -r a7e20b0b5c43 src/ipsec.h
---- a/src/ipsec.h Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/ipsec.h Tue Jan 08 11:28:48 2008 +0100
-@@ -82,15 +82,30 @@ int ha_ipsec_tnl_update(const struct in6
- const struct in6_addr *hoa,
- const struct in6_addr *coa,
- const struct in6_addr *old_coa,
-- int tunnel);
-+ int tunnel,
-+ struct list_head *mnp);
-+
-+int ha_ipsec_mnp_pol_del(const struct in6_addr *our_addr,
-+ const struct in6_addr *peer_addr,
-+ struct list_head *old_mnps,
-+ struct list_head *new_mnps,
-+ int tunnel);
-+
-+int ha_ipsec_mnp_pol_add(const struct in6_addr *our_addr,
-+ const struct in6_addr *peer_addr,
-+ struct list_head *old_mnps,
-+ struct list_head *new_mnps,
-+ int tunnel);
-
- int ha_ipsec_tnl_pol_add(const struct in6_addr *our_addr,
- const struct in6_addr *peer_addr,
-- int tunnel);
-+ int tunnel,
-+ struct list_head *mnp);
-
- int ha_ipsec_tnl_pol_del(const struct in6_addr *our_addr,
- const struct in6_addr *peer_addr,
-- int tunnel);
-+ int tunnel,
-+ struct list_head *mnp);
-
- int mn_ipsec_tnl_update(const struct in6_addr *haaddr,
- const struct in6_addr *hoa,
-diff -r a7e20b0b5c43 src/mh.c
---- a/src/mh.c Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/mh.c Tue Jan 08 11:28:48 2008 +0100
-@@ -51,6 +51,7 @@
- #include "conf.h"
- #include "bcache.h"
- #include "keygen.h"
-+#include "prefix.h"
-
- #define MH_DEBUG_LEVEL 1
-
-@@ -75,6 +76,7 @@ int mh_opts_dup_ok[] = {
- 0, /* Alternate CoA */
- 0, /* Nonce Index */
- 0, /* Binding Auth Data */
-+ 1, /* Mobile Network Prefix */
- };
-
- #define __MH_SENTINEL (IP6_MH_TYPE_MAX + 1)
-@@ -401,6 +403,46 @@ static int create_opt_pad(struct iovec *
- return 0;
- }
-
-+int mh_create_opt_mob_net_prefix(struct iovec *iov, int mnp_count,
-+ struct list_head *mnps)
-+{
-+ int optlen = (mnp_count * sizeof(struct ip6_mh_opt_mob_net_prefix) +
-+ (mnp_count - 1) * sizeof(_pad4));
-+ struct list_head *l;
-+ int i = 0;
-+ uint8_t *data;
-+ iov->iov_base = malloc(optlen);
-+ iov->iov_len = optlen;
-+
-+ if (iov->iov_base == NULL)
-+ return -ENOMEM;
-+
-+ memset(iov->iov_base, 0, iov->iov_len);
-+ data = (uint8_t *)iov->iov_base;
-+
-+ list_for_each(l, mnps) {
-+ struct prefix_list_entry *p;
-+ struct ip6_mh_opt_mob_net_prefix *mnp;
-+
-+ p = list_entry(l, struct prefix_list_entry, list);
-+ mnp = (struct ip6_mh_opt_mob_net_prefix *)data;
-+
-+ mnp->ip6mnp_type = IP6_MHOPT_MOB_NET_PRFX;
-+ mnp->ip6mnp_len = 18;
-+ mnp->ip6mnp_prefix_len = p->ple_plen;
-+ mnp->ip6mnp_prefix = p->ple_prefix;
-+
-+ data += sizeof(struct ip6_mh_opt_mob_net_prefix);
-+
-+ /* do internal padding here, so one iovec for MNPs is enough */
-+ if (++i < mnp_count) {
-+ memcpy(data, _pad4, sizeof(_pad4));
-+ data += sizeof(_pad4);
-+ }
-+ }
-+ return 0;
-+}
-+
- static size_t mh_length(struct iovec *vec, int count)
- {
- size_t len = 0;
-@@ -441,6 +483,9 @@ static int mh_try_pad(const struct iovec
- break;
- case IP6_MHOPT_BAUTH:
- pad = optpad(8, 2, len); /* 8n+2 */
-+ break;
-+ case IP6_MHOPT_MOB_NET_PRFX:
-+ pad = optpad(8, 4, len); /* 8n+4 */
- break;
- }
- if (pad > 0) {
-@@ -694,6 +739,8 @@ static int mh_opt_len_chk(uint8_t type,
- return len != sizeof(struct ip6_mh_opt_nonce_index);
- case IP6_MHOPT_BAUTH:
- return len != sizeof(struct ip6_mh_opt_auth_data);
-+ case IP6_MHOPT_MOB_NET_PRFX:
-+ return len != sizeof(struct ip6_mh_opt_mob_net_prefix);
- case IP6_MHOPT_PADN:
- default:
- return 0;
-diff -r a7e20b0b5c43 src/mh.h
---- a/src/mh.h Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/mh.h Tue Jan 08 11:28:48 2008 +0100
-@@ -10,7 +10,7 @@
-
- /* If new types or options appear, these should be updated. */
- #define IP6_MH_TYPE_MAX IP6_MH_TYPE_BERROR
--#define IP6_MHOPT_MAX IP6_MHOPT_BAUTH
-+#define IP6_MHOPT_MAX IP6_MHOPT_MOB_NET_PRFX
-
- struct in6_addr_bundle {
- struct in6_addr *src;
-@@ -74,6 +74,11 @@ int mh_create_opt_nonce_index(struct iov
-
- int mh_create_opt_auth_data(struct iovec *iov);
-
-+struct list_head;
-+
-+int mh_create_opt_mob_net_prefix(struct iovec *iov, int mnp_count,
-+ struct list_head *mnps);
-+
- static inline void *mh_opt(const struct ip6_mh *mh,
- const struct mh_options *mh_opts, uint8_t type)
- {
-diff -r a7e20b0b5c43 src/mn.c
---- a/src/mn.c Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/mn.c Tue Jan 08 11:28:48 2008 +0100
-@@ -326,7 +326,17 @@ static int mn_send_bu_msg(struct bulentr
- free_iov_data(iov, iov_ind);
- return -ENOMEM;
- }
-- if (!(bule->flags & IP6_MH_BU_HOME)) {
-+ if (bule->flags & IP6_MH_BU_HOME) {
-+ struct home_addr_info *hai = bule->home;
-+ if (bule->flags & IP6_MH_BU_MR && bu->ip6mhbu_lifetime &&
-+ bule->home->mnp_count > 0 && conf.MobRtrUseExplicitMode &&
-+ mh_create_opt_mob_net_prefix(&iov[iov_ind++],
-+ hai->mnp_count,
-+ &hai->mob_net_prefixes) < 0) {
-+ free_iov_data(iov, iov_ind);
-+ return -ENOMEM;
-+ }
-+ } else {
- if (mh_create_opt_nonce_index(&iov[iov_ind++], bule->rr.ho_ni,
- bule->rr.co_ni) ||
- mh_create_opt_auth_data(&iov[iov_ind++])) {
-@@ -616,6 +626,34 @@ static int mv_hoa(struct ifaddrmsg *ifa,
- return 0;
- }
-
-+int nemo_mr_tnl_routes_add(struct home_addr_info *hai, int ifindex)
-+{
-+ struct list_head *l;
-+ struct prefix_list_entry *pe;
-+ list_for_each(l, &hai->mob_net_prefixes) {
-+ struct prefix_list_entry *p;
-+ p = list_entry(l, struct prefix_list_entry, list);
-+ if (route_add(ifindex, RT6_TABLE_MIP6, RTPROT_MIP,
-+ 0, IP6_RT_PRIO_MIP6_FWD,
-+ &p->ple_prefix, p->ple_plen,
-+ &in6addr_any, 0, NULL) < 0) {
-+ pe = p;
-+ goto undo;
-+ }
-+ }
-+ return 0;
-+undo:
-+ list_for_each(l, &hai->mob_net_prefixes) {
-+ struct prefix_list_entry *p;
-+ p = list_entry(l, struct prefix_list_entry, list);
-+ route_del(ifindex, RT6_TABLE_MIP6, IP6_RT_PRIO_MIP6_FWD,
-+ &p->ple_prefix, p->ple_plen, &in6addr_any, 0, NULL);
-+ if (p == pe)
-+ break;
-+ }
-+ return -1;
-+}
-+
- static int mn_tnl_state_add(struct home_addr_info *hai, int ifindex, int all)
- {
- int err = 0;
-@@ -628,12 +666,31 @@ static int mn_tnl_state_add(struct home_
- mn_ro_pol_del(hai, ifindex, all);
- }
- }
-+ if (hai->mob_rtr &&
-+ (err = nemo_mr_tnl_routes_add(hai, ifindex)) < 0) {
-+ route_del(ifindex, RT6_TABLE_MIP6, IP6_RT_PRIO_MIP6_OUT,
-+ &hai->hoa.addr, 128, &in6addr_any, 0, NULL);
-+ mn_ro_pol_del(hai, ifindex, all);
-+ }
- return err;
-+}
-+
-+static void nemo_mr_tnl_routes_del(struct home_addr_info *hai, int ifindex)
-+{
-+ struct list_head *l;
-+ list_for_each(l, &hai->mob_net_prefixes) {
-+ struct prefix_list_entry *p;
-+ p = list_entry(l, struct prefix_list_entry, list);
-+ route_del(ifindex, RT6_TABLE_MIP6, IP6_RT_PRIO_MIP6_FWD,
-+ &p->ple_prefix, p->ple_plen, &in6addr_any, 0, NULL);
-+ }
- }
-
- static void mn_tnl_state_del(struct home_addr_info *hai, int ifindex, int all)
- {
- if (hai->home_reg_status != HOME_REG_NONE) {
-+ if (hai->mob_rtr)
-+ nemo_mr_tnl_routes_del(hai, ifindex);
- route_del(ifindex, RT6_TABLE_MIP6, IP6_RT_PRIO_MIP6_OUT,
- &hai->hoa.addr, 128, &in6addr_any, 0, NULL);
- mn_ro_pol_del(hai, ifindex, all);
-@@ -674,7 +731,8 @@ static int process_first_home_bu(struct
- {
- int err = 0;
- bule->type = BUL_ENTRY;
-- bule->flags = IP6_MH_BU_HOME | IP6_MH_BU_ACK | hai->lladdr_comp;
-+ bule->flags = (IP6_MH_BU_HOME | IP6_MH_BU_ACK |
-+ hai->lladdr_comp | hai->mob_rtr);
- bule->coa_changed = -1;
- bule->coa = hai->primary_coa.addr;
- bule->if_coa = hai->primary_coa.iif;
-@@ -1084,6 +1142,18 @@ static void mn_recv_ba(const struct ip6_
- if (bule->flags & IP6_MH_BU_HOME) {
- struct home_addr_info *hai = bule->home;
- struct ip6_mh_opt_refresh_advice *bra;
-+
-+ if (bule->flags & IP6_MH_BU_MR &&
-+ !(ba->ip6mhba_flags & IP6_MH_BA_MR)) {
-+ if (hai->use_dhaad) {
-+ mn_change_ha(hai);
-+ } else {
-+ int one = 1;
-+ bul_iterate(&hai->bul, mn_dereg, &one);
-+ }
-+ pthread_rwlock_unlock(&mn_lock);
-+ return;
-+ }
- if (!tsisset(ba_lifetime)) {
- int type = FLUSH_FAILED;
- mn_dereg_home(hai);
-@@ -1251,12 +1321,73 @@ static int flag_hoa(struct ifaddrmsg *if
- return 0;
- }
-
-+static void nemo_mr_rules_del(struct home_addr_info *hinfo)
-+{
-+ struct list_head *l;
-+
-+ list_for_each(l, &hinfo->mob_net_prefixes) {
-+ struct prefix_list_entry *p = NULL;
-+ p = list_entry(l, struct prefix_list_entry, list);
-+ rule_del(NULL, RT6_TABLE_MIP6,
-+ IP6_RULE_PRIO_MIP6_FWD, RTN_UNICAST,
-+ &p->ple_prefix, p->ple_plen, &in6addr_any, 0, 0);
-+ rule_del(NULL, RT6_TABLE_MAIN,
-+ IP6_RULE_PRIO_MIP6_MNP_IN, RTN_UNICAST,
-+ &in6addr_any, 0, &p->ple_prefix, p->ple_plen, 0);
-+ }
-+}
-+
-+static int nemo_mr_rules_add(struct home_addr_info *hinfo)
-+{
-+ struct prefix_list_entry *pe = NULL;
-+ struct list_head *l;
-+
-+ list_for_each(l, &hinfo->mob_net_prefixes) {
-+ struct prefix_list_entry *p = NULL;
-+ p = list_entry(l, struct prefix_list_entry, list);
-+ if (rule_add(NULL, RT6_TABLE_MAIN,
-+ IP6_RULE_PRIO_MIP6_MNP_IN, RTN_UNICAST,
-+ &in6addr_any, 0,
-+ &p->ple_prefix, p->ple_plen, 0) < 0) {
-+ pe = p;
-+ goto undo;
-+ }
-+ if (rule_add(NULL, RT6_TABLE_MIP6,
-+ IP6_RULE_PRIO_MIP6_FWD, RTN_UNICAST,
-+ &p->ple_prefix, p->ple_plen,
-+ &in6addr_any, 0, 0) < 0) {
-+ rule_del(NULL, RT6_TABLE_MAIN,
-+ IP6_RULE_PRIO_MIP6_MNP_IN, RTN_UNICAST,
-+ &in6addr_any, 0, &p->ple_prefix, p->ple_plen, 0);
-+ pe = p;
-+ goto undo;
-+ }
-+ }
-+ return 0;
-+undo:
-+ list_for_each(l, &hinfo->mob_net_prefixes) {
-+ struct prefix_list_entry *p = NULL;
-+ p = list_entry(l, struct prefix_list_entry, list);
-+ rule_del(NULL, RT6_TABLE_MIP6,
-+ IP6_RULE_PRIO_MIP6_FWD, RTN_UNICAST,
-+ &p->ple_prefix, p->ple_plen, &in6addr_any, 0, 0);
-+ rule_del(NULL, RT6_TABLE_MAIN,
-+ IP6_RULE_PRIO_MIP6_MNP_IN, RTN_UNICAST,
-+ &in6addr_any, 0, &p->ple_prefix, p->ple_plen, 0);
-+ if (p == pe)
-+ break;
-+ }
-+ return -1;
-+}
-+
- static void clean_home_addr_info(struct home_addr_info *hai)
- {
- struct flag_hoa_args arg;
- int plen = (hai->hoa.iif == hai->if_tunnel ? 128 : hai->plen);
-
- list_del(&hai->list);
-+ if (hai->mob_rtr)
-+ nemo_mr_rules_del(hai);
- arg.target = hai;
- arg.flag = 0;
- addr_do(&hai->hoa.addr, plen,
-@@ -1310,13 +1441,23 @@ static struct home_addr_info *hai_copy(s
-
- if (pthread_mutex_init(&hai->ha_list.c_lock, NULL))
- goto undo;
-+
-+ INIT_LIST_HEAD(&hai->mob_net_prefixes);
-+ if (hai->mob_rtr &&
-+ prefix_list_copy(&conf_hai->mob_net_prefixes,
-+ &hai->mob_net_prefixes) < 0)
-+ goto mutex_undo;
-+
- INIT_LIST_HEAD(&hai->ro_policies);
- if (rpl_copy(&conf_hai->ro_policies, &hai->ro_policies) < 0)
-- goto mutex_undo;
-+ goto mnp_undo;
-+
- INIT_LIST_HEAD(&hai->ha_list.tqe.list);
- INIT_LIST_HEAD(&hai->ha_list.home_agents);
- }
- return hai;
-+mnp_undo:
-+ prefix_list_free(&hai->mob_net_prefixes);
- mutex_undo:
- pthread_mutex_destroy(&hai->ha_list.c_lock);
- undo:
-@@ -1337,6 +1478,15 @@ static int conf_home_addr_info(struct ho
- if ((hai = hai_copy(conf_hai)) == NULL)
- goto err;
-
-+ if (hai->mob_rtr) {
-+ MDBG("is Mobile Router\n");
-+ list_for_each(list, &hai->mob_net_prefixes) {
-+ struct prefix_list_entry *p;
-+ p = list_entry(list, struct prefix_list_entry, list);
-+ MDBG("Mobile Network Prefix %x:%x:%x:%x:%x:%x:%x:%x/%d\n",
-+ NIP6ADDR(&p->ple_prefix), p->ple_plen);
-+ }
-+ }
- if (IN6_IS_ADDR_UNSPECIFIED(&hai->ha_addr)) {
- hai->use_dhaad = 1;
- } else {
-@@ -1379,6 +1529,9 @@ static int conf_home_addr_info(struct ho
-
- if (addr_do(&hai->hoa.addr, 128,
- hai->if_tunnel, &arg, flag_hoa) < 0) {
-+ goto clean_err;
-+ }
-+ if (hai->mob_rtr && nemo_mr_rules_add(hai) < 0) {
- goto clean_err;
- }
- hai->at_home = hai->hoa.iif == hai->if_home;
-diff -r a7e20b0b5c43 src/mn.h
---- a/src/mn.h Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/mn.h Tue Jan 08 11:28:48 2008 +0100
-@@ -45,9 +45,11 @@ struct ha_candidate_list {
- pthread_mutex_t c_lock;
- };
-
--#define HOME_LINK_BLOCK 0x1
--#define HOME_ADDR_BLOCK 0x2
--#define HOME_ADDR_RULE_BLOCK 0x4
-+#define HOME_LINK_BLOCK 0x01
-+#define HOME_ADDR_BLOCK 0x02
-+#define HOME_ADDR_RULE_BLOCK 0x04
-+#define NEMO_RA_BLOCK 0x08
-+#define NEMO_FWD_BLOCK 0x10
-
- struct mn_addr {
- struct in6_addr addr;
-@@ -84,7 +86,10 @@ struct home_addr_info {
- int if_block;
- short hwalen;
- uint8_t altcoa;
-+ uint16_t mob_rtr;
- char name[IF_NAMESIZE];
-+ int mnp_count;
-+ struct list_head mob_net_prefixes;
- };
-
- enum {
-diff -r a7e20b0b5c43 src/movement.c
---- a/src/movement.c Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/movement.c Tue Jan 08 11:28:48 2008 +0100
-@@ -78,6 +78,7 @@ static int conf_default_rs = 3;
- static int conf_default_rs = 3;
- static int conf_default_rs_ival = 4;
-
-+static int conf_forwarding = 0;
- static int conf_autoconf = 1;
- static int conf_ra_defrtr = 0;
- static int conf_rs = 0;
-@@ -177,6 +178,12 @@ static void __md_free_router(struct md_r
-
- route_del(rtr->ifindex, RT_TABLE_MAIN, 0,
- &in6addr_any, 0, &in6addr_any, 0, &rtr->lladdr);
-+
-+ /* delete default route for the packets coming from the
-+ * Mobile Network
-+ */
-+ route_del(rtr->ifindex, RT6_TABLE_MIP6, 0,
-+ &in6addr_any, 0, &in6addr_any, 0, &rtr->lladdr);
- }
- list_for_each_safe(l, n, &rtr->prefixes) {
- struct prefix_list_entry *p;
-@@ -231,8 +238,31 @@ static void md_expire_coa(struct md_inet
- list_add_tail(&coa->list, &iface->expired_coas);
- }
-
-+static void md_reset_egress_forward(void)
-+{
-+ struct list_head *l;
-+ int forward = 0;;
-+
-+ if (list_empty(&ifaces))
-+ return;
-+
-+ list_for_each(l, &ifaces) {
-+ struct md_inet6_iface *i;
-+ i = list_entry(l, struct md_inet6_iface, list);
-+ forward |= i->home_link;
-+ }
-+ list_for_each(l, &ifaces) {
-+ struct md_inet6_iface *i;
-+ i = list_entry(l, struct md_inet6_iface, list);
-+ set_iface_proc_entry(PROC_SYS_IP6_FORWARDING,
-+ i->name, forward);
-+ }
-+}
-+
- static void md_reset_home_link(struct md_inet6_iface *i)
- {
-+ if (i->home_link)
-+ md_reset_egress_forward();
- i->home_link = 0;
- i->ll_dad_unsafe = 0;
- }
-@@ -648,6 +678,8 @@ md_create_inet6_iface(struct ifinfomsg *
-
- static void iface_proc_entries_init(struct md_inet6_iface *iface)
- {
-+ set_iface_proc_entry(PROC_SYS_IP6_FORWARDING, iface->name,
-+ conf_forwarding);
- set_iface_proc_entry(PROC_SYS_IP6_AUTOCONF, iface->name,
- conf_autoconf);
- set_iface_proc_entry(PROC_SYS_IP6_ACCEPT_RA_DEFRTR, iface->name, conf_ra_defrtr);
-@@ -878,6 +910,8 @@ static void md_check_home_link(struct md
- ll_dad_unsafe |= hai->lladdr_comp;
- }
- }
-+ if (i->home_link != home_link)
-+ md_reset_egress_forward();
- i->home_link = home_link;
- i->ll_dad_unsafe = ll_dad_unsafe;
- }
-@@ -1189,6 +1223,11 @@ static void md_update_router_stats(struc
- RTF_DEFAULT|RTF_ADDRCONF, 1024,
- &in6addr_any, 0, &in6addr_any, 0, &rtr->lladdr);
-
-+ /* default route for the packet coming from the Mobile Network */
-+ route_add(rtr->ifindex, RT6_TABLE_MIP6, RTPROT_MIP,
-+ 0, IP6_RT_PRIO_MIP6_FWD,
-+ &in6addr_any, 0, &in6addr_any, 0, &rtr->lladdr);
-+
- list_for_each(list, &rtr->prefixes) {
- struct prefix_list_entry *p;
- p = list_entry(list, struct prefix_list_entry, list);
-@@ -1737,6 +1776,8 @@ static void iface_default_proc_entries_c
-
- static void iface_proc_entries_cleanup(struct md_inet6_iface *iface)
- {
-+ set_iface_proc_entry(PROC_SYS_IP6_FORWARDING, iface->name,
-+ iface->devconf[DEVCONF_FORWARDING]);
- set_iface_proc_entry(PROC_SYS_IP6_AUTOCONF, iface->name,
- iface->devconf[DEVCONF_AUTOCONF]);
- set_iface_proc_entry(PROC_SYS_IP6_ACCEPT_RA_DEFRTR, iface->name,
-diff -r a7e20b0b5c43 src/ndisc.c
---- a/src/ndisc.c Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/ndisc.c Tue Jan 08 11:28:48 2008 +0100
-@@ -106,7 +106,7 @@ int proxy_nd_start(int ifindex, struct i
- {
- struct in6_addr lladdr;
- int err;
-- int nd_flags = 0;
-+ int nd_flags = bu_flags&IP6_MH_BU_MR ? NTF_ROUTER : 0;
-
- err = pneigh_add(ifindex, nd_flags, target);
-
-@@ -117,7 +117,9 @@ int proxy_nd_start(int ifindex, struct i
- pneigh_del(ifindex, target);
- }
- if (!err) {
-- uint32_t na_flags = ND_NA_FLAG_OVERRIDE;
-+ uint32_t na_flags = (ND_NA_FLAG_OVERRIDE |
-+ nd_flags ? ND_NA_FLAG_ROUTER : 0);
-+
- ndisc_send_na(ifindex, src, &in6addr_all_nodes_mc,
- target, na_flags);
-
-diff -r a7e20b0b5c43 src/policy.c
---- a/src/policy.c Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/policy.c Tue Jan 08 11:28:48 2008 +0100
-@@ -107,6 +107,23 @@ int default_max_binding_life(const struc
- return 0;
- }
-
-+static inline int
-+policy_check_mob_net_prefix(const struct policy_bind_acl_entry *acl,
-+ const struct ip6_mh_binding_update *bu,
-+ const struct mh_options *opts)
-+{
-+ struct ip6_mh_opt_mob_net_prefix *op;
-+ for (op = mh_opt(&bu->ip6mhbu_hdr, opts, IP6_MHOPT_MOB_NET_PRFX);
-+ op != NULL;
-+ op = mh_opt_next(&bu->ip6mhbu_hdr, opts, op)) {
-+ if (!prefix_list_get(&acl->mob_net_prefixes,
-+ &op->ip6mnp_prefix,
-+ op->ip6mnp_prefix_len))
-+ return IP6_MH_BAS_NOT_AUTH_FOR_PRFX;
-+ }
-+ return IP6_MH_BAS_ACCEPTED;
-+}
-+
- /**
- * default_discard_binding - check for discard policy
- * @remote_hoa: remote MN's home address
-@@ -127,10 +144,20 @@ int default_discard_binding(const struct
- int ret = def_bind_policy;
- struct policy_bind_acl_entry *acl;
-
-+ if (bu->ip6mhbu_flags & IP6_MH_BU_MR && !conf.HaAcceptMobRtr)
-+ return IP6_MH_BAS_MR_OP_NOT_PERMITTED;
-+
- pthread_rwlock_rdlock(&policy_lock);
- acl = hash_get(&policy_bind_acl_hash, NULL, remote_hoa);
- if (acl != NULL) {
- ret = acl->bind_policy;
-+ if (ret < IP6_MH_BAS_UNSPECIFIED &&
-+ bu->ip6mhbu_flags & IP6_MH_BU_MR) {
-+ struct mh_options opts;
-+ mh_opt_parse(&bu->ip6mhbu_hdr, len,
-+ sizeof(*bu), &opts);
-+ ret = policy_check_mob_net_prefix(acl, bu, &opts);
-+ }
- }
- pthread_rwlock_unlock(&policy_lock);
- return ret;
-@@ -227,6 +254,42 @@ int default_best_ro_coa(const struct in6
- return 0;
- }
-
-+int default_get_mnp_count(const struct in6_addr *hoa)
-+{
-+ int ret = 0;
-+ struct policy_bind_acl_entry *acl;
-+ pthread_rwlock_rdlock(&policy_lock);
-+ acl = hash_get(&policy_bind_acl_hash, NULL, hoa);
-+ if (acl != NULL)
-+ ret = acl->mnp_count;
-+ pthread_rwlock_unlock(&policy_lock);
-+ return ret;
-+
-+}
-+
-+int default_get_mnps(const struct in6_addr *hoa,
-+ const int mnp_count,
-+ struct nd_opt_prefix_info *mnps)
-+{
-+ int i = 0;
-+ struct policy_bind_acl_entry *acl;
-+
-+ pthread_rwlock_rdlock(&policy_lock);
-+ acl = hash_get(&policy_bind_acl_hash, NULL, hoa);
-+ if (acl != NULL) {
-+ struct list_head *l;
-+ list_for_each(l, &acl->mob_net_prefixes) {
-+ struct prefix_list_entry *e;
-+ if (i >= mnp_count)
-+ break;
-+ e = list_entry(l, struct prefix_list_entry, list);
-+ mnps[i++] = e->pinfo;
-+ }
-+ }
-+ pthread_rwlock_unlock(&policy_lock);
-+ return i;
-+}
-+
- static int policy_bind_acle_cleanup(void *data, void *arg)
- {
- struct policy_bind_acl_entry *acl = data;
-diff -r a7e20b0b5c43 src/policy.h
---- a/src/policy.h Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/policy.h Tue Jan 08 11:28:48 2008 +0100
-@@ -10,12 +10,15 @@
-
- struct ip6_mh_binding_update;
- struct nd_router_advert;
-+struct nd_opt_prefix_info;
-
- struct policy_bind_acl_entry {
- struct list_head list;
- struct in6_addr hoa;
- int plen;
- int bind_policy;
-+ int mnp_count;
-+ struct list_head mob_net_prefixes;
- };
-
- /**
-@@ -147,6 +150,12 @@ int default_best_ro_coa(const struct in6
- const struct in6_addr *cn,
- struct in6_addr *coa);
-
-+int default_get_mnp_count(const struct in6_addr *hoa);
-+
-+int default_get_mnps(const struct in6_addr *hoa,
-+ const int mnp_count,
-+ struct nd_opt_prefix_info *mnps);
-+
- void policy_cleanup(void);
-
- int policy_init(void);
-diff -r a7e20b0b5c43 src/proc_sys.h
---- a/src/proc_sys.h Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/proc_sys.h Tue Jan 08 11:28:48 2008 +0100
-@@ -14,6 +14,7 @@
- #define PROC_SYS_IP6_APP_SOLICIT "/proc/sys/net/ipv6/neigh/%s/app_solicit"
- #define PROC_SYS_IP6_BASEREACHTIME_MS "/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms"
- #define PROC_SYS_IP6_RETRANSTIMER_MS "/proc/sys/net/ipv6/neigh/%s/retrans_time_ms"
-+#define PROC_SYS_IP6_FORWARDING "/proc/sys/net/ipv6/conf/%s/forwarding"
-
- int set_iface_proc_entry(const char *tmpl, const char *if_name, int val);
-
-diff -r a7e20b0b5c43 src/rtnl.h
---- a/src/rtnl.h Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/rtnl.h Tue Jan 08 11:28:48 2008 +0100
-@@ -16,6 +16,7 @@
- #define IP6_RT_PRIO_MIP6_FWD 192
- #define IP6_RT_PRIO_ADDRCONF 256
-
-+#define IP6_RULE_PRIO_MIP6_MNP_IN 1000
- #define IP6_RULE_PRIO_MIP6_HOA_OUT 1001
- #define IP6_RULE_PRIO_MIP6_COA_OUT 1002
- #define IP6_RULE_PRIO_MIP6_BLOCK 1003
-diff -r a7e20b0b5c43 src/scan.l
---- a/src/scan.l Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/scan.l Tue Jan 08 11:28:48 2008 +0100
-@@ -136,6 +136,11 @@ MnRouterProbeTimeout { return MNROUTERP
- MnRouterProbeTimeout { return MNROUTERPROBETIMEOUT; }
- MnDiscardHaParamProb { return MNDISCARDHAPARAMPROB; }
- OptimisticHandoff { return OPTIMISTICHANDOFF; }
-+HaAcceptMobRtr { return HAACCEPTMOBRTR; }
-+IsMobRtr { return ISMOBRTR; }
-+HaServedPrefix { return HASERVEDPREFIX; }
-+HomePrefix { return HOMEPREFIX; }
-+MobRtrUseExplicitMode { return MOBRTRUSEEXPLICITMODE; }
- internal { return INTERNAL; }
-
- {addr} {
-diff -r a7e20b0b5c43 src/vt.c
---- a/src/vt.c Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/vt.c Tue Jan 08 11:28:48 2008 +0100
-@@ -677,6 +677,16 @@ static int bcache_vt_dump(void *data, vo
- }
-
- fprintf(vh->vh_stream, "\n");
-+
-+ /* Dump the registered MNP */
-+ {
-+ struct list_head *l;
-+ list_for_each(l, &bce->mob_net_prefixes) {
-+ struct prefix_list_entry *p;
-+ p = list_entry(l, struct prefix_list_entry, list);
-+ fprintf(vh->vh_stream, " MNP: %x:%x:%x:%x:%x:%x:%x:%x/%d\n", NIP6ADDR(&p->ple_prefix), p->ple_plen);
-+ }
-+ }
-
- return 0;
- }
-diff -r a7e20b0b5c43 src/xfrm.c
---- a/src/xfrm.c Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/xfrm.c Tue Jan 08 11:28:48 2008 +0100
-@@ -679,12 +679,73 @@ static int _mn_ha_ipsec_bypass_init(cons
- return err;
- }
-
-+static int mr_ipsec_bypass_init(void)
-+{
-+ struct list_head *home;
-+ struct list_head *mnps;
-+ int err=0;
-+
-+ /* Loop for each HomeAddress info */
-+ list_for_each(home, &conf.home_addrs)
-+ {
-+ struct home_addr_info *hai;
-+ hai = list_entry(home, struct home_addr_info, list);
-+
-+ /* If Mobile Router for this link, loop for each MNP */
-+ if (hai->mob_rtr)
-+ {
-+ /* Add bypass policies to and from the MNP link */
-+ list_for_each(mnps, &hai->mob_net_prefixes)
-+ {
-+ struct prefix_list_entry * mnp;
-+ struct xfrm_selector sel;
-+
-+ mnp = list_entry(mnps, struct prefix_list_entry, list);
-+
-+ memset(&sel, 0, sizeof(sel));
-+ sel.family = AF_INET6;
-+ sel.user = getuid();
-+
-+ /* IN, src = MNP , dst = any */
-+ memcpy(&sel.saddr.a6, &mnp->ple_prefix, sizeof(sel.saddr.a6));
-+ sel.prefixlen_s = mnp->ple_plen;
-+
-+ err = xfrm_ipsec_policy_add(&sel, 0, XFRM_POLICY_IN,
-+ XFRM_POLICY_ALLOW, MIP6_PRIO_MR_LOCAL_DATA_BYPASS,
-+ NULL, 0);
-+
-+ /* XXX: what should we do in case of error? */
-+
-+ /* FWD, src = MNP , dst = any */
-+ err = xfrm_ipsec_policy_add(&sel, 0, XFRM_POLICY_FWD,
-+ XFRM_POLICY_ALLOW, MIP6_PRIO_MR_LOCAL_DATA_BYPASS,
-+ NULL, 0);
-+
-+ /* OUT, src = any , dst = MNP */
-+ memset(&sel.saddr.a6, 0, sizeof(sel.saddr.a6));
-+ sel.prefixlen_s = 0;
-+ memcpy(&sel.daddr.a6, &mnp->ple_prefix, sizeof(sel.daddr.a6));
-+ sel.prefixlen_d = mnp->ple_plen;
-+
-+ err = xfrm_ipsec_policy_add(&sel, 0, XFRM_POLICY_OUT,
-+ XFRM_POLICY_ALLOW, MIP6_PRIO_MR_LOCAL_DATA_BYPASS,
-+ NULL, 0);
-+ }
-+ }
-+ }
-+
-+ return err;
-+}
-+
- static inline int mn_ha_ipsec_init(void)
- {
- int err;
-
- /* insert bypass policy */
- err = ipsec_policy_walk(_mn_ha_ipsec_bypass_init, NULL);
-+
-+ /* insert NEMO-related bypass */
-+ err = mr_ipsec_bypass_init();
-
- err = ipsec_policy_walk(_mn_ha_ipsec_init, NULL);
-
-@@ -787,9 +848,64 @@ static int _mn_ha_ipsec_bypass_cleanup(c
- return err;
- }
-
-+static int mr_ipsec_bypass_cleanup(void)
-+{
-+ struct list_head *home;
-+ struct list_head *mnps;
-+ int err=0;
-+
-+ /* Loop for each HomeAddress info */
-+ list_for_each(home, &conf.home_addrs)
-+ {
-+ struct home_addr_info *hai;
-+ hai = list_entry(home, struct home_addr_info, list);
-+
-+ /* If Mobile Router for this link, loop for each MNP */
-+ if (hai->mob_rtr)
-+ {
-+ /* Delete bypass policies to and from the MNP link */
-+ list_for_each(mnps, &hai->mob_net_prefixes)
-+ {
-+ struct prefix_list_entry * mnp;
-+ struct xfrm_selector sel;
-+
-+ mnp = list_entry(mnps, struct prefix_list_entry, list);
-+
-+ memset(&sel, 0, sizeof(sel));
-+ sel.family = AF_INET6;
-+ sel.user = getuid();
-+
-+ /* IN, src = MNP , dst = any */
-+ memcpy(&sel.saddr.a6, &mnp->ple_prefix, sizeof(sel.saddr.a6));
-+ sel.prefixlen_s = mnp->ple_plen;
-+
-+ err = xfrm_ipsec_policy_del(&sel, XFRM_POLICY_IN);
-+
-+ /* XXX: what should we do in case of error? */
-+
-+ /* FWD, src = MNP , dst = any */
-+ err = xfrm_ipsec_policy_del(&sel, XFRM_POLICY_FWD);
-+
-+ /* OUT, src = any , dst = MNP */
-+ memset(&sel.saddr.a6, 0, sizeof(sel.saddr.a6));
-+ sel.prefixlen_s = 0;
-+ memcpy(&sel.daddr.a6, &mnp->ple_prefix, sizeof(sel.daddr.a6));
-+ sel.prefixlen_d = mnp->ple_plen;
-+
-+ err = xfrm_ipsec_policy_del(&sel, XFRM_POLICY_OUT);
-+ }
-+ }
-+ }
-+
-+ return err;
-+}
-+
-+
- static inline void mn_ha_ipsec_cleanup(void)
- {
- ipsec_policy_walk(_mn_ha_ipsec_bypass_cleanup, NULL);
-+
-+ (void)mr_ipsec_bypass_cleanup();
-
- ipsec_policy_walk(_mn_ha_ipsec_cleanup, NULL);
- }
-@@ -1719,6 +1835,8 @@ int xfrm_pre_bu_add_bule(struct bulentry
- if (hai->home_block & HOME_LINK_BLOCK)
- xfrm_unblock_link(hai);
- xfrm_block_link(hai);
-+ if (hai->mob_rtr && !(hai->home_block & NEMO_FWD_BLOCK))
-+ xfrm_block_fwd(hai);
- }
- if (IN6_ARE_ADDR_EQUAL(&bule->hoa, &bule->coa)) {
- if (rdata)
-@@ -1784,6 +1902,8 @@ int xfrm_post_ba_mod_bule(struct bulentr
- struct home_addr_info *hai = bule->home;
- if (hai->home_block & HOME_LINK_BLOCK)
- xfrm_unblock_link(hai);
-+ if (hai->home_block & NEMO_FWD_BLOCK)
-+ xfrm_unblock_fwd(hai);
- }
- /* check if XFRM policies and states have already been cleaned up */
- if (IN6_ARE_ADDR_EQUAL(&bule->hoa, &bule->coa))
-@@ -2058,6 +2178,50 @@ void xfrm_unblock_hoa(struct home_addr_i
- hai->home_block &= ~HOME_ADDR_BLOCK;
- }
-
-+/* block all RA messages sent by MR */
-+int xfrm_block_ra(struct home_addr_info *hai)
-+{
-+ int ret = 0;
-+ struct xfrm_selector sel;
-+ hai->home_block |= NEMO_RA_BLOCK;
-+ set_selector(&in6addr_any, &in6addr_any, IPPROTO_ICMPV6,
-+ ND_ROUTER_ADVERT, 0, 0, &sel);
-+ if ((ret = xfrm_mip_policy_add(&sel, 0, XFRM_POLICY_OUT, XFRM_POLICY_BLOCK,
-+ MIP6_PRIO_HOME_BLOCK, NULL, 0)))
-+ return ret;
-+ return ret;
-+}
-+
-+void xfrm_unblock_ra(struct home_addr_info *hai)
-+{
-+ struct xfrm_selector sel;
-+ set_selector(&in6addr_any, &in6addr_any, IPPROTO_ICMPV6,
-+ ND_ROUTER_ADVERT, 0, 0, &sel);
-+ xfrm_mip_policy_del(&sel, XFRM_POLICY_OUT);
-+ hai->home_block &= ~NEMO_RA_BLOCK;
-+}
-+
-+/* block all forwarded packets */
-+int xfrm_block_fwd(struct home_addr_info *hai)
-+{
-+ int ret = 0;
-+ struct xfrm_selector sel;
-+ hai->home_block |= NEMO_FWD_BLOCK;
-+ set_selector(&in6addr_any, &in6addr_any, 0, 0, 0, 0, &sel);
-+ if ((ret = xfrm_mip_policy_add(&sel, 0, XFRM_POLICY_FWD, XFRM_POLICY_BLOCK,
-+ MIP6_PRIO_HOME_BLOCK, NULL, 0)))
-+ return ret;
-+ return ret;
-+}
-+
-+void xfrm_unblock_fwd(struct home_addr_info *hai)
-+{
-+ struct xfrm_selector sel;
-+ set_selector(&in6addr_any, &in6addr_any, 0, 0, 0, 0, &sel);
-+ xfrm_mip_policy_del(&sel, XFRM_POLICY_FWD);
-+ hai->home_block &= ~NEMO_FWD_BLOCK;
-+}
-+
- int mn_ipsec_recv_bu_tnl_pol_add(struct bulentry *bule, int ifindex,
- struct ipsec_policy_entry *e)
- {
-diff -r a7e20b0b5c43 src/xfrm.h
---- a/src/xfrm.h Wed Nov 28 16:43:32 2007 +0100
-+++ b/src/xfrm.h Tue Jan 08 11:28:48 2008 +0100
-@@ -15,6 +15,7 @@
- #define MIP6_PRIO_RO_SIG_IPSEC 7 /* XXX: BU between MN-MN with IPsec */
- #define MIP6_PRIO_RO_SIG 8 /* XXX: BU between MN-CN */
- #define MIP6_PRIO_RO_SIG_ANY 9
-+#define MIP6_PRIO_MR_LOCAL_DATA_BYPASS 9 /* Bypass rule for local traffic in mobile network */
- #define MIP6_PRIO_RO_SIG_RR 10 /* XXX: MH(or HoTI/HoT) between MN-CN */
- #define MIP6_PRIO_RO_BLOCK 11
- #define MIP6_PRIO_NO_RO_SIG_ANY 12
-@@ -87,6 +88,12 @@ int xfrm_block_hoa(struct home_addr_info
- int xfrm_block_hoa(struct home_addr_info *hai);
- void xfrm_unblock_hoa(struct home_addr_info *hai);
-
-+int xfrm_block_ra(struct home_addr_info *hai);
-+void xfrm_unblock_ra(struct home_addr_info *hai);
-+
-+int xfrm_block_fwd(struct home_addr_info *hai);
-+void xfrm_unblock_fwd(struct home_addr_info *hai);
-+
- int ha_mn_ipsec_pol_mod(struct in6_addr *haaddr,
- struct in6_addr *hoa);
-
diff --git a/openair3/NEMO_SHO/mipv6-daemon-umip-0.4-nepl-mcoa-20080108.patch b/openair3/NEMO_SHO/mipv6-daemon-umip-0.4-nepl-mcoa-20080108.patch
deleted file mode 100755
index 11217388cf4dfb57b61f20c87d40cb056d08dec7..0000000000000000000000000000000000000000
--- a/openair3/NEMO_SHO/mipv6-daemon-umip-0.4-nepl-mcoa-20080108.patch
+++ /dev/null
@@ -1,5535 +0,0 @@
-diff -r 82fcd4bea972 NEWS.MCOA
---- /dev/null Thu Jan 01 00:00:00 1970 +0000
-+++ b/NEWS.MCOA Fri Jan 11 17:02:25 2008 +0100
-@@ -0,0 +1,103 @@
-+mipv6-daemon-umip-0.4-nepl-mcoa-20080108.patch
-+News and Bugfixes list since mipv6-daemon-umip-0.3-nepl-mcoa-20071022.patch:
-+
-+* Updated code on top of the latest NEPL patch
-+* No new features
-+
-+-----------------------------------------------------------------------
-+mipv6-daemon-umip-0.4-nepl-mcoa-20071022.patch
-+News and Bugfixes list since mipv6-daemon-umip-0.3-nepl-mcoa-20070613.patch:
-+
-+* Ported the code to UMIP 0.4. MCoA now runs on a 2.6.23 kernel,
-+ with an UMIP 0.4-based code for the userland.
-+* Merged a fix to the proxy ND code for the HA (provided by
-+ Tobias HOF): the HA can now be used as legacy node on the
-+ Home Link (whereas it only worked as a gateway before).
-+
-+-----------------------------------------------------------------------
-+mipv6-daemon-umip-0.3-nepl-mcoa-20070613.patch
-+News and Bugfixes list since nemo-0.2-mcoa-beta2-20060630:
-+
-+* Ported the code to UMIP. MCoA now runs on a 2.6.21.3 kernel,
-+ with an UMIP-based code for the userland.
-+* MCoA is now provided as a patch for the UMIP userland.
-+* The MCoA kernel patch is not needed anymore as it has been
-+ integrated in the mainline kernel.
-+* No new functionnalities were added.
-+
-+-----------------------------------------------------------------------
-+nemo-0.2-mcoa-beta3-20070118
-+News and Bugfixes list since nemo-0.2-mcoa-beta2-20060630:
-+
-+* Base code:
-+- Userland runs on a 2.6.16 kernel
-+- Upgraded fwmark patch for 2.6.16 kernel
-+- MCoA userland code updated to nemo-20060725
-+
-+* Features:
-+- New "Reliable" option that allows to use the BU as a
-+ heartbeat, and to automatically divert the traffic to
-+ another interface when one MR-HA path fails.
-+ See the manpage for details.
-+- MPS/MPA can now be used with MCoA.
-+- When handover occurs on an interface, forwarded traffic is now
-+ blocked only for the interface performing the handover (whereas
-+ it was blocked globally before). The local traffic is also
-+ blocked for the interface that performs the handover, whereas
-+ it was blocked for the HoA interface before.
-+- Merged patch to support HoA from MNP (for Mobile Routers)
-+- Merged patch to support SIT tunnels
-+- Merged patch to fix the MR behaviour in the Home Network
-+ (the MR was not correctly forwarding packets from the MNNs)
-+
-+* Bugfixes:
-+- The source address used to send the BU was sometimes outdated
-+ because the CoA was not correctly updated in the XFRM kernel
-+ state.
-+- When packets originated from the MR were sent to the HA, the
-+ HA did not behave correctly because the source address of the
-+ packet may not match the one in the kernel XFRM state (that
-+ can only store one CoA). Thus the MR behaviour has been
-+ slightly changed to NOT use HAO dest. option when sending
-+ packet to the HA (This behaviour seems to respect the MIP6
-+ spec).
-+- When packets originated from the MR were sent to the HA, and
-+ the MR handoffs, the HA still sent replied packets to the
-+ old CoA (using Routing Header Type 2). The HA now updates
-+ correctly the CoA stored in the kernel, but as the kernel
-+ can only store 1 CoA at a time, when the HA replies to the
-+ MR the path may be asymetric.
-+- Added more checks in the configuration file grammar to
-+ avoid configuration errors for MCoA.
-+- Solved infinite loop when interface was declared as Interface
-+ but not in IfMultipleCoA.
-+- Fixed some bugs when MCoA was disabled. It now works fine when
-+ not using MCoA. Interface prefence works also fine.
-+- Fixed bugs when one entry was invalidated: rules are now
-+ correctly deleted.
-+- Fixed bugs when choosing the default rule: invalid BULE are
-+ not looked up when searching for the default rule.
-+- Improved the MR and HA behaviour regarding error management.
-+
-+
-+-----------------------------------------------------------------------
-+nemo-0.2-mcoa-beta2-20060630
-+News and Bugfixes list since nemo-0.2-mcoa-beta1-20060531:
-+
-+- The MR was in some cases installing the same rules twice.
-+- The MR had a problem to install some rules after recovering a failure.
-+- The MR was stuck in an infinite loop at startup if MCoA was disabled
-+- The MR could not clean properly tunnels if registration failed with HA
-+- Policy issues when Returning home with a usual MR but using MCoA code
-+- When the MR only have 1 active interface, handoff policy is different
-+ (rules not erased and dereg bu not send during handoff time)
-+- When the MR receives a BAck without BID option, whereas it sent a BU
-+ with a BID option, the MR only registers the prefered interface
-+
-+- If HA is not configured for MCoA, or MCoA not allowed for the HoA, then
-+ BU is accepted but no BID option is sent in BAck
-+
-+- Merged the OptimisticHandoff patch
-+- Merged the PPP patch
-+
-+-----------------------------------------------------------------------
-diff -r 82fcd4bea972 README.MCOA
---- /dev/null Thu Jan 01 00:00:00 1970 +0000
-+++ b/README.MCOA Fri Jan 11 17:02:25 2008 +0100
-@@ -0,0 +1,154 @@
-+--------------------------------------------
-+Multiple CoA implementation on UMIP
-+
-+ver. 20080108
-+--------------------------------------------
-+Romain KUNTZ
-+Jean LORCHAT
-+Nautilus6 Project
-+--------------------------------------------
-+
-+
-+1. What is Multiple CoA?
-+------------------------
-+
-+Multiple CoA (Multiple Care-of Addresses Registration, MCoA) allows
-+a Mobile Node to register multiple Care-of Addresses at the same
-+time to its Home Agent. Main benefits, amongst others, are policy
-+routing and fault tolerance for the Mobile Router.
-+
-+The current implementation is based on
-+draft-ietf-monami6-multiplecoa-01 and is shipped as a tarball
-+that contains kernel patches and the userland.
-+
-+This implementation is based on UMIP, a Mobility platform on Linux.
-+More information about UMIP can be found on
-+
-+
-+
-+2. Limitations
-+--------------
-+
-+Due to its early stage of development, the MCoA implementation still
-+have some important limitations. Please read them carefully to
-+understand what you cannot do with this implementation:
-+
-+- IPsec is not yet supported. It will in the future, but we now
-+ concentrate on the non-IPsec part.
-+
-+- Returning home is not supported. Do not try to boot your MN at home
-+ or to return home with one of its interface, this will not work.
-+ This feature will be available in the future.
-+
-+- Once the MN has established multiple tunnels, the policy routing
-+ only works FOR THE FORWARDED TRAFFIC. The traffic generated by the
-+ MN itself will not be routed according to your policies. Only the
-+ traffic from the MNN, routed via the Mobile Router, will be routed
-+ according to the policies you installed on the MR. You can expect
-+ some improvements in the next releases.
-+
-+- CN are not supported, ie the MN cannot register multiple CoA to
-+ the CN.
-+
-+- The BID for each interface must be chosen between 1 and 251. This
-+ limitation is due to the implementation design. We will try to
-+ improve this point in the future.
-+
-+- This implementation does not support yet the Bulk Registration,
-+ mainly because Bulk registration is still under discussion at
-+ the IETF.
-+
-+
-+3. Known Bugs
-+-------------
-+
-+- Binding Refresh Request do not include the BID option
-+- Binding Error do not include the BID option
-+- The BU is sometimes sent via another interface than expected.
-+- Certainly many others!
-+
-+4. Instructions
-+---------------
-+
-+a. Testbed Setup
-+----------------
-+
-+Testbed setup, kernel and userlan compilation, configuration
-+files etc. are explained in the NEPL Howto available on:
-+http://www.nautilus6.org/doc/nepl-howto/
-+
-+Please check this document (especially section 6) to setup
-+your MCoA testbed.
-+
-+b. Policy Routing
-+-----------------
-+
-+Once your MN has registered multiple CoA to your Home Agent, it can
-+use its multiple MN-HA tunnel for policy routing.
-+
-+The policy routing part is managed with ip6tables. Be sure to install
-+this tool on both your HA and MN.
-+
-+- How does it work?
-+-------------------
-+
-+The BID that you assigned to each interface will be used to mark the
-+packets. Packets marked with BID X will be routed through the
-+interface whose BID is X. If this interface is not available (because
-+it is down), then the packet will be routed through the most prefered
-+interface (the one with the best BidPriority).
-+
-+NOTE:
-+At the moment, ONLY PACKETS FORWARDED BY THE MR (ie packets sent by MNN)
-+can benefit from the policy routing. Packets generated by the MR itself
-+will not be routed according to your rules. We are currently working to
-+improve the current situation to also allow the MR to benefit from the
-+policy routing.
-+
-+
-+- How to mark a packet?
-+-----------------------
-+
-+Use the ip6tables tool and the MARK target to mark your packets with
-+the BID. Ip6tables rules must be done in the PREROUTING chain, in the
-+mangle table.
-+
-+For example, on the MN, to mark as 100 all icmpv6 packets whose
-+destination is 2001:a:b::1000, you can do:
-+
-+ip6tables -A PREROUTING -t mangle
-+ -p icmpv6 --destination 2001:a:b::1000
-+ -j MARK --set-mark 100
-+
-+Those packets will be sent through the interface whose BID is 100.
-+You will also need to create the "symetric" rule on the Home Agent:
-+
-+ip6tables -A PREROUTING -t mangle
-+ -p icmpv6 --source 2001:a:b::1000
-+ -j MARK --set-mark 100
-+
-+As you see, one current limitation is that each rules created on the
-+MN must be also created on the Home Agent. We plan to support in the
-+future some policy exchange mechanism between the MN and the HA in
-+order to configure automatically the HA.
-+
-+Read carefully the ip6tables manpage. You will be able to create
-+rules based on many parameters, and thus create a very subtle policy
-+routing on your MN.
-+
-+
-+5. Support
-+----------
-+
-+The MCoA implementation is not supported by the UMIP team, so please
-+do not complain on their Mailing List. If you have any questions
-+regarding this work, or any BUG report, feel free to subscribe to
-+our support and announce mailing lists:
-+
-+http://www.nautilus6.org/ml.php
-+
-+--------------------------------------------
-+Romain KUNTZ
-+Jean LORCHAT
-+Nautilus6 Project
-+--------------------------------------------
-diff -r 82fcd4bea972 include/netinet/ip6mh.h
---- a/include/netinet/ip6mh.h Fri Jan 11 16:55:08 2008 +0100
-+++ b/include/netinet/ip6mh.h Fri Jan 11 17:02:25 2008 +0100
-@@ -146,6 +146,25 @@ struct ip6_mh_opt_mob_net_prefix {
- } __attribute__ ((packed));
-
- /*
-+ * MCoA registration
-+ * Binding Unique Identifier sub-option
-+ */
-+struct ip6_mh_opt_bid {
-+ uint8_t ip6mobid_type;
-+ uint8_t ip6mobid_len;
-+ uint16_t ip6mobid_bid;
-+ uint8_t ip6mobid_priority;
-+ uint8_t ip6mobid_reserved;
-+} __attribute__((packed));
-+
-+/* Binding Unique Identifier sub-option flags */
-+#if BYTE_ORDER == BIG_ENDIAN
-+#define IP6_OPT_BID_BULK 0x80 /* Bulk Registration */
-+#else /* BYTE_ORDER == LITTLE_ENDIAN */
-+#define IP6_OPT_BID_BULK 0x80 /* Bulk Registration */
-+#endif
-+
-+/*
- * Mobility Header Message Types
- */
- #define IP6_MH_TYPE_BRR 0 /* Binding Refresh Request */
-@@ -167,6 +186,7 @@ struct ip6_mh_opt_mob_net_prefix {
- #define IP6_MHOPT_NONCEID 0x04 /* Nonce Index */
- #define IP6_MHOPT_BAUTH 0x05 /* Binding Auth Data */
- #define IP6_MHOPT_MOB_NET_PRFX 0x06 /* Mobile Network Prefix */
-+#define IP6_MHOPT_BID 0x07 /* Binding Unique Identifier */
-
- /*
- * Status values accompanied with Mobility Binding Acknowledgement
-@@ -191,6 +211,9 @@ struct ip6_mh_opt_mob_net_prefix {
- #define IP6_MH_BAS_INVAL_PRFX 141 /* Invalid Prefix */
- #define IP6_MH_BAS_NOT_AUTH_FOR_PRFX 142 /* Not Authorized for Prefix */
- #define IP6_MH_BAS_FWDING_FAILED 143 /* Forwarding Setup failed */
-+#define IP6_MH_BAS_CONFLICT_BINDING 144 /* (TBD) MCoA Conflict between bindings */
-+#define IP6_MH_BAS_MCOA_BULK_FAILED 145 /* (TBD) MCoA Bulk registration failed */
-+
- /*
- * Status values for the Binding Error mobility messages
- */
-diff -r 82fcd4bea972 man/mip6d.conf.tmpl
---- a/man/mip6d.conf.tmpl Fri Jan 11 16:55:08 2008 +0100
-+++ b/man/mip6d.conf.tmpl Fri Jan 11 17:02:25 2008 +0100
-@@ -57,6 +57,9 @@ These options are used both in the Home
- .BR "Interface " "name" " {"
- .BR " MnIfPreference " "number" ";"
- .BR " IfType " "CN | HA | MN" ";"
-+.BR " Bid " "number" ";"
-+.BR " BidPriority " "number" ";"
-+.BR " Reliable " "boolean" ";"
- .B }
- .fi
-
-@@ -74,9 +77,10 @@ sets the interface preference value for
- sets the interface preference value for an interface in a multi-homed
- Mobile Node. The most preferred intefaces have preference 1, the
- second most preferred have 2, etc. A preference of zero means the
--interface will not be used.
-+interface will not be used. Do not use this option if you use the Multiple
-+Care-of Address registration on your Mobile Node with this interface.
-
--Default: 5
-+Default: 0
-
- .B IfType
- overrides the default node behavior for this interface. If a MN doesn't
-@@ -86,6 +90,43 @@ Default: same as
- Default: same as
- .B NodeConfig
-
-+.B Bid
-+Sets the BID for this interface. The BID must be unique within all
-+interface definitions. This BID will be used as an Interface Identifier
-+that the user can use for policy routing. If this option is defined,
-+also set the
-+.B BidPriority
-+option, and do not set the
-+.B MnIfPreference
-+option.
-+.B Bid
-+must be set between 1 and 251 (this is one of the current limitation
-+with this MCoA implementation).
-+
-+Default: 0 (no BID)
-+
-+.B BidPriority
-+Sets the priority of the binding (the higher the better). When no
-+policies are define for some flows, the binding with the higher
-+preference is used. If this option is defined, do not set the
-+.B MnIfPreference
-+option for this interface.
-+.B BidPriority
-+must be set between 1 and 255.
-+
-+Default: 0
-+
-+.B Reliable
-+allows you to specify if the interface can be considered as reliable
-+when using MCoA. If set to false, the traffic will be redirected to
-+another interface during the BU-BAck exchange. You can thus use the
-+BU as a heartbeat (by specifying a small
-+.B MnMaxHaBindingLife
-+), which can be pretty useful when one of your MR-HA path is not
-+reliable: traffic is redirected to the interface with the best
-+priority as long as no BAck is received.
-+
-+Default: true
-
- .TP
- .BR "UseMnHaIPsec " "boolean" ";"
-@@ -191,6 +232,13 @@ Default: disabled;
- Default: disabled;
-
- .TP
-+.BR "HaAcceptMCoAReg enabled | disabled"
-+
-+Indicates if the HA accepts Multiple Care-of Addresses registration.
-+
-+Default: disabled;
-+
-+.TP
- .BR "HaServedPrefix " "prefix/length" ";"
-
- Prefix is an IPv6 prefix and length is the prefix length. Defines the whole
-@@ -199,7 +247,7 @@ Mobile Network Prefixes, instead of one
- Mobile Network Prefixes, instead of one of the home link prefixes.
-
- .TP
--.BR "BindingAclPolicy " "address MNP list " "allow | deny"
-+.BR "BindingAclPolicy " "address MNP list " "MCoAReg | NoMCoAReg " "allow | deny"
-
- Defines if a MN is allowed to register with the HA or not. The home address
- of the MN is given in the address field. The mobile network prefixes
-@@ -207,6 +255,12 @@ be an empty string or a comma separated
- be an empty string or a comma separated list of network prefixes
- enclosed in braces, for example:
- .B "(3ffe:2620:6:3::/64, 3ffe:2620:6:4::/64)"
-+The HA can forbid or allow the MN to register Multiple Care-of Addresses by
-+setting the
-+.B NoMCoAReg
-+or
-+.B MCoAReg
-+flag.
-
- .TP
- .BR "DefaultBindingAclPolicy allow | deny"
-@@ -368,6 +422,31 @@ Default: disabled
- Default: disabled
-
- .TP
-+.BR "RegMultipleCoA enabled | disabled"
-+
-+Defines if the Mobile Node should try to register Multiple Care-of
-+Addresses to its Home Agent. If enabled, use also the
-+.B IfMultipleCoA
-+option. If disabled, the node will only register one CoA at a time.
-+
-+Default: disabled;
-+
-+.TP
-+.BR "IfMultipleCoA " "name1, name2, ..." ";"
-+
-+Defines the list of interfaces that will be used for Multiple Care-of
-+Addresses registration. This list must be composed with the names
-+(enclosed in double quotes) of the interfaces (eg. "eth1"), separated
-+with a coma. Each interface listed must have an
-+.B Interface
-+definition properly filled with the Multiple Care-of Address options
-+(
-+.B Bid
-+and
-+.B BidPriority
-+).
-+
-+.TP
- The route optimization policies are of the form:
-
- .TP
-@@ -389,7 +468,7 @@ matching this entry.
- .SH EXAMPLES
-
- .TP
--.BR "A NEMO Home Agent example:"
-+.BR "A NEMO Home Agent example with MCoA support:"
-
- .nf
- NodeConfig HA;
-@@ -397,18 +476,19 @@ Interface "eth0";
- Interface "eth0";
-
- HaAcceptMobRtr enabled;
-+HaAcceptMCoAReg enabled;
-
- HaServedPrefix 3ffe:2620:6::/48;
-
- DefaultBindingAclPolicy deny;
--BindingAclPolicy 3ffe:2620:6:1::1234 (3ffe:2620:6:2::/64, 3ffe:2620:6:3::/64) allow;
-+BindingAclPolicy 3ffe:2620:6:1::1234 (3ffe:2620:6:2::/64, 3ffe:2620:6:3::/64) MCoAReg allow;
- BindingAclPolicy 3ffe:2620:6:1::1235 allow;
-
- UseMnHaIPsec disabled;
- .fi
-
- .TP
--.BR "A NEMO Mobile Router example:"
-+.BR "A NEMO Mobile Router example with MCoA support:"
-
- .nf
- NodeConfig MN;
-@@ -416,7 +496,15 @@ DoRouteOptimizationCN disabled;
- DoRouteOptimizationCN disabled;
- DoRouteOptimizationMN disabled;
-
--Interface "eth0";
-+Interface "eth0" {
-+ Bid 111;
-+ BidPriority 10;
-+};
-+
-+Interface "eth1" {
-+ Bid 222;
-+ BidPriority 5;
-+};
-
- MnRouterProbes 1;
-
-@@ -426,6 +514,8 @@ MnHomeLink "eth0" {
- IsMobRtr enabled;
- HomeAgentAddress 3ffe:2620:6:1::1;
- HomeAddress 3ffe:2620:6:1::1234/64 (3ffe:2620:6:2::/64, 3ffe:2620:6:3::/64);
-+ RegMultipleCoA enabled;
-+ IfMultipleCoA "eth0", "eth1";
- }
-
- UseMnHaIPsec disabled;
-diff -r 82fcd4bea972 src/bcache.c
---- a/src/bcache.c Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/bcache.c Fri Jan 11 17:02:25 2008 +0100
-@@ -48,6 +48,7 @@ static int bcache_count = 0;
- static int bcache_count = 0;
-
- pthread_rwlock_t bc_lock; /* Protects binding cache */
-+int bce_next_entry(void *bce_v, void *next_bce_v);
-
- /**
- * get_bcache_count - returns number of home and cache entries
-@@ -90,6 +91,12 @@ void dump_bce(void *bce, void *os)
- fprintf(out, " lifetime %ld\n ", e->lifetime.tv_sec);
- fprintf(out, " seqno %d\n", e->seqno);
-
-+ if (e->bid)
-+ fprintf(out, " BID = %d, Priority = %d\n",
-+ e->bid, e->priority);
-+ else
-+ fprintf(out, " No BID assigned\n");
-+
- if (e->flags & IP6_MH_BA_MR) {
- struct list_head *list;
-
-@@ -201,6 +208,7 @@ void bcache_free(struct bcentry *bce)
- * @hinfo: home address info, optional if our_addr is present
- * @our_addr: local address (home address)
- * @peer_addr: address of CN
-+ * @bid: BID of the bce
- *
- * Returns reference to non-null entry on success and null on failure.
- * If caller adjusts lifetime of entry, caller must call
-@@ -208,7 +216,8 @@ void bcache_free(struct bcentry *bce)
- * call bcache_release_entry() after entry is not used anymore.
- **/
- struct bcentry *bcache_get(const struct in6_addr *our_addr,
-- const struct in6_addr *peer_addr)
-+ const struct in6_addr *peer_addr,
-+ uint16_t bid)
- {
- struct bcentry *bce;
-
-@@ -216,7 +225,7 @@ struct bcentry *bcache_get(const struct
-
- pthread_rwlock_rdlock(&bc_lock);
-
-- bce = hash_get(&bc_hash, our_addr, peer_addr);
-+ bce = hash_get(&bc_hash, our_addr, peer_addr, bid);
-
- if (bce)
- pthread_rwlock_wrlock(&bce->lock);
-@@ -240,16 +249,19 @@ void bcache_release_entry(struct bcentry
- * bce_type - get type of binding cache entry
- * @our_addr: our IPv6 address
- * @peer_addr: peer's IPv6 address
-+ * @bid: BID of the bce
- *
- * Looks up entry from binding cache and returns its type. If not
- * found, returns -%ENOENT.
- **/
--int bce_type(const struct in6_addr *our_addr, const struct in6_addr *peer_addr)
-+int bce_type(const struct in6_addr *our_addr,
-+ const struct in6_addr *peer_addr,
-+ uint16_t bid)
- {
- struct bcentry *bce;
- int type;
-
-- bce = bcache_get(our_addr, peer_addr);
-+ bce = bcache_get(our_addr, peer_addr, bid);
-
- if (bce == NULL)
- return -ENOENT;
-@@ -264,7 +276,8 @@ static int __bcache_insert(struct bcentr
- {
- int ret;
-
-- ret = hash_add(&bc_hash, bce, &bce->our_addr, &bce->peer_addr);
-+ ret = hash_add(&bc_hash, bce, &bce->our_addr,
-+ &bce->peer_addr, &bce->bid);
- if (ret)
- return ret;
-
-@@ -282,7 +295,14 @@ static int __bcache_start(struct bcentry
- bce->type == BCE_HOMEREG ? bce->lifetime : tmp,
- expires);
- add_task_abs(&expires, &bce->tqe, _expire);
-- xfrm_add_bce(&bce->our_addr, &bce->peer_addr, &bce->coa, 0);
-+ /* MCoA
-+ * Due to the BID, the BC may have several entries with the
-+ * same peer_addr. Thus we add states and policies only if
-+ * there are no entries yet for the our_addr/peer_addr pair
-+ * (see bce->xfrm_create).
-+ */
-+ xfrm_add_bce(&bce->our_addr, &bce->peer_addr, &bce->coa, 0,
-+ bce->xfrm_create);
- return 0;
- }
-
-@@ -350,22 +370,26 @@ int bcache_update_expire(struct bcentry
- }
- tsadd(expires, bce->add_time, expires);
- add_task_abs(&expires, &bce->tqe, _expire);
-- xfrm_add_bce(&bce->our_addr, &bce->peer_addr, &bce->coa, 1);
-+ xfrm_add_bce(&bce->our_addr, &bce->peer_addr, &bce->coa, 1, 0);
-
- return 0;
- }
-
- /**
- * bcache_delete - deletes a bul entry
-+ * If bid == 0, all entries that match our_addr/peer_addr are deleted
- **/
- void bcache_delete(const struct in6_addr *our_addr,
-- const struct in6_addr *peer_addr)
-+ const struct in6_addr *peer_addr,
-+ uint16_t bid)
- {
- struct bcentry *bce;
- pthread_rwlock_wrlock(&bc_lock);
-- bce = hash_get(&bc_hash, our_addr, peer_addr);
-- if (bce)
-- bce_delete(bce, 0);
-+ while ((bce = hash_get(&bc_hash, our_addr, peer_addr, bid))) {
-+ if (bce)
-+ bce_delete(bce, 0);
-+ }
-+
- pthread_rwlock_unlock(&bc_lock);
- }
-
-@@ -398,8 +422,27 @@ static void bce_delete(struct bcentry *b
- pthread_rwlock_wrlock(&bce->lock);
- if (bce->type != BCE_DAD) {
- del_task(&bce->tqe);
-- if (bce->type != BCE_NONCE_BLOCK)
-- xfrm_del_bce(&bce->our_addr, &bce->peer_addr);
-+ if (bce->type != BCE_NONCE_BLOCK) {
-+ /* MCoA
-+ * Due to the BID, the BC can have several entries
-+ * with the same our_addr/peer_addr pair. We delete
-+ * the xfrm data if we do not have any BCE for
-+ * this peer_addr anymore, or we update it (we need
-+ * to update the kernel's CoA to a valid one).
-+ */
-+ if(mcoa_bce_count(&bce->peer_addr) == 1)
-+ xfrm_del_bce(&bce->our_addr, &bce->peer_addr);
-+ else {
-+ struct bcentry *next = bce;
-+ /* Look for another valid BCE */
-+ bcache_iterate_in(&bce->peer_addr,
-+ bce_next_entry, &next);
-+ /* Replace the CoA */
-+ xfrm_add_bce(&next->our_addr,
-+ &next->peer_addr,
-+ &next->coa, 1, 0);
-+ }
-+ }
- }
- if (bce->cleanup)
- bce->cleanup(bce);
-@@ -414,7 +457,7 @@ static void bce_delete(struct bcentry *b
- }
- }
- bcache_count--;
-- hash_delete(&bc_hash, &bce->our_addr, &bce->peer_addr);
-+ hash_delete(&bc_hash, &bce->our_addr, &bce->peer_addr, bce->bid);
- pthread_rwlock_unlock(&bce->lock);
- bcache_free(bce);
- }
-@@ -458,3 +501,71 @@ int bcache_iterate(int (* func)(void *,
- pthread_rwlock_unlock(&bc_lock);
- return err;
- }
-+
-+/**
-+ * bcache_iterate_in - apply function to every BC entry that match peer_addr
-+ * @peer_addr: the peer_addr of the hash
-+ * @func: function to apply
-+ * @arg: extra data for @func
-+ *
-+ * Iterates through binding cache, calling @func for each entry that
-+ * match peer_addr. Extra data may be passed to @func in @arg. @func
-+ * takes a bcentry as its first argument and @arg as second argument.
-+ *
-+ * Be sure that bc_lock is locked before using this function, and
-+ * unlocked after using it.
-+ **/
-+int bcache_iterate_in(const struct in6_addr *peer_addr,
-+ int (* func)(void *, void *),
-+ void *arg)
-+{
-+ int err;
-+ err = hash_iterate_in(&bc_hash, peer_addr, func, arg);
-+ return err;
-+}
-+
-+int bce_highest_priority(void *bce_v, void *best_bce_v)
-+{
-+ struct bcentry *bce = bce_v;
-+ struct bcentry **best_bce = best_bce_v;
-+
-+ assert(bce);
-+ assert(best_bce);
-+
-+ if (!(*best_bce) || (bce->priority > (*best_bce)->priority))
-+ (*best_bce) = bce;
-+
-+ return 0;
-+}
-+
-+int bce_next_entry(void *bce_v, void *next_bce_v)
-+{
-+ struct bcentry *bce = bce_v;
-+ struct bcentry **next_bce = next_bce_v;
-+
-+ assert(bce);
-+ assert(next_bce);
-+
-+ if (bce->bid != (*next_bce)->bid) {
-+ (*next_bce) = bce;
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+int mcoa_bce_inc_counter(void *bule_v, void *counter_v)
-+{
-+ int *counter = counter_v;
-+ (*counter)++;
-+ return 0;
-+}
-+
-+int mcoa_bce_count(const struct in6_addr *peer_addr)
-+{
-+ int count = 0;
-+ bcache_iterate_in(peer_addr, mcoa_bce_inc_counter, &count);
-+
-+ return count;
-+}
-+
-diff -r 82fcd4bea972 src/bcache.h
---- a/src/bcache.h Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/bcache.h Fri Jan 11 17:02:25 2008 +0100
-@@ -20,6 +20,12 @@ struct bcentry {
- uint16_t nonce_hoa;
- uint16_t type; /* Entry type */
- uint16_t nemo_type; /* NEMO registration type */
-+ uint16_t bid; /* MCoA: Binding Identifier */
-+ uint8_t priority; /* MCoA: BID priority */
-+ int table; /* MCoA: Table id to where are stored
-+ the routes */
-+ int xfrm_create; /* MCoA: If xfrm policies/states must
-+ be created */
- int unreach; /* ICMP dest unreach count */
- int tunnel; /* Tunnel interface index */
- int link; /* Home link interface index */
-@@ -48,12 +54,16 @@ struct bcentry {
- #define BCE_NEMO_IMPLICIT 2
- #define BCE_NEMO_DYNAMIC 3
-
-+#define BCE_TABLE_MIN 1
-+#define BCE_TABLE_MAX 251
-+
- struct bcentry *bcache_alloc(int type);
-
- void bcache_free(struct bcentry *bce);
-
- struct bcentry *bcache_get(const struct in6_addr *our_addr,
-- const struct in6_addr *peer_addr);
-+ const struct in6_addr *peer_addr,
-+ uint16_t bid);
-
- int bcache_add(struct bcentry *bce);
-
-@@ -63,28 +73,37 @@ int bcache_update_expire(struct bcentry
- int bcache_update_expire(struct bcentry *bce);
-
- void bcache_delete(const struct in6_addr *our_addr,
-- const struct in6_addr *peer_addr);
-+ const struct in6_addr *peer_addr,
-+ uint16_t bid);
-
- int bcache_init(void);
- void bcache_flush(void);
- void bcache_cleanup(void);
-
- int bcache_iterate(int (* func)(void *, void *), void *arg);
-+int bcache_iterate_in(const struct in6_addr *peer_addr,
-+ int (* func)(void *, void *),
-+ void *arg);
-
- void bcache_release_entry(struct bcentry *bce);
-
- int bce_type(const struct in6_addr *our_addr,
-- const struct in6_addr *peer_addr);
-+ const struct in6_addr *peer_addr,
-+ uint16_t bid);
-
- static inline int bce_exists(const struct in6_addr *our_addr,
-- const struct in6_addr *peer_addr)
-+ const struct in6_addr *peer_addr,
-+ uint16_t bid)
- {
-- return bce_type(our_addr, peer_addr) >= BCE_NONCE_BLOCK;
-+ return bce_type(our_addr, peer_addr, bid) >= BCE_NONCE_BLOCK;
- }
-+
-+int bce_highest_priority(void *bce_v, void *best_bce_v);
-
- void dump_bce(void *bce, void *os);
-
- int get_bcache_count(int type);
-+int mcoa_bce_count(const struct in6_addr *peer_addr);
-
- extern pthread_rwlock_t bc_lock; /* Protects binding cache */
-
-diff -r 82fcd4bea972 src/bul.c
---- a/src/bul.c Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/bul.c Fri Jan 11 17:02:25 2008 +0100
-@@ -38,6 +38,8 @@
- #include "xfrm.h"
- #include "debug.h"
- #include "retrout.h"
-+#include "tunnelctl.h"
-+#include "rtnl.h"
- #ifdef ENABLE_VT
- #include "vt.h"
- #endif
-@@ -55,7 +57,8 @@ static struct hash bul_hash;
- static struct hash bul_hash;
-
- struct bulentry *create_bule(const struct in6_addr *hoa,
-- const struct in6_addr *cn_addr)
-+ const struct in6_addr *cn_addr,
-+ u_int16_t bid)
- {
- struct bulentry *bule;
- if ((bule = malloc(sizeof(*bule))) != NULL) {
-@@ -63,6 +66,11 @@ struct bulentry *create_bule(const struc
- bule->hoa = *hoa;
- bule->last_coa = *hoa;
- bule->peer_addr = *cn_addr;
-+ bule->bid = bid;
-+ bule->if_tunnel = 0;
-+ bule->rules = 0;
-+ bule->home_block = 0;
-+ bule->mcoa_dereg = 1;
- INIT_LIST_HEAD(&bule->tqe.list);
- bule->seq = random();
- }
-@@ -97,6 +105,11 @@ void dump_bule(void *bule, void *os)
- NIP6ADDR(&e->peer_addr));
- fprintf(out, " lifetime = %ld, ", e->lifetime.tv_sec);
- fprintf(out, " delay = %ld\n", tstomsec(e->delay));
-+ if (e->bid)
-+ fprintf(out, " BID = %d, Priority = %d\n",
-+ e->bid, e->priority);
-+ else
-+ fprintf(out, " No BID assigned\n");
- fprintf(out, " flags: ");
- if (e->flags & IP6_MH_BU_HOME)
- fprintf(out, "IP6_MH_BU_HOME ");
-@@ -118,21 +131,23 @@ void dump_bule(void *bule, void *os)
- * @hinfo: home address info, optional if our_addr is present
- * @our_addr: local address (home address)
- * @peer_addr: address of CN
-+ * @bid: Binding Unique Identifier
- *
- * Returns non-null entry on success and null on failure. Caller must
- * call del_task and add_task, if lifetime of the entry is changed.
- **/
- struct bulentry *bul_get(struct home_addr_info *hinfo,
- const struct in6_addr *our_addr,
-- const struct in6_addr *peer_addr)
-+ const struct in6_addr *peer_addr,
-+ u_int16_t bid)
- {
- struct bulentry *bule;
-
- assert(hinfo || our_addr);
-
- if (hinfo)
-- bule = hash_get(&hinfo->bul, NULL, peer_addr);
-- else bule = hash_get(&bul_hash, our_addr, peer_addr);
-+ bule = hash_get(&hinfo->bul, NULL, peer_addr, bid);
-+ else bule = hash_get(&bul_hash, our_addr, peer_addr, bid);
- return bule;
- }
-
-@@ -175,9 +190,11 @@ int bul_add(struct bulentry *bule)
-
- assert(bule && tsisset(bule->lifetime) && hai);
-
-- if ((ret = hash_add(&bul_hash, bule, &bule->hoa, &bule->peer_addr)) < 0)
-+ if ((ret = hash_add(&bul_hash, bule, &bule->hoa, &bule->peer_addr,
-+ &bule->bid)) < 0)
- return ret;
-- if ((ret = hash_add(&hai->bul, bule, NULL, &bule->peer_addr)) < 0)
-+ if ((ret = hash_add(&hai->bul, bule, NULL, &bule->peer_addr,
-+ &bule->bid)) < 0)
- goto bul_free;
-
- clock_gettime(CLOCK_REALTIME, &bule->lastsent);
-@@ -197,9 +214,9 @@ int bul_add(struct bulentry *bule)
- add_task_abs(&timer_expire, &bule->tqe, bule->callback);
- return 0;
- home_bul_free:
-- hash_delete(&hai->bul, &bule->hoa, &bule->peer_addr);
-+ hash_delete(&hai->bul, &bule->hoa, &bule->peer_addr, bule->bid);
- bul_free:
-- hash_delete(&bul_hash, &bule->hoa, &bule->peer_addr);
-+ hash_delete(&bul_hash, &bule->hoa, &bule->peer_addr, bule->bid);
- return ret;
- }
-
-@@ -209,8 +226,8 @@ void bul_delete(struct bulentry *bule)
- struct home_addr_info *hai = bule->home;
-
- del_task(&bule->tqe);
-- hash_delete(&bul_hash, &bule->hoa, &bule->peer_addr);
-- hash_delete(&hai->bul, NULL, &bule->peer_addr);
-+ hash_delete(&bul_hash, &bule->hoa, &bule->peer_addr, bule->bid);
-+ hash_delete(&hai->bul, NULL, &bule->peer_addr, bule->bid);
-
- if (!IN6_ARE_ADDR_EQUAL(&bule->hoa, &bule->coa)) {
- bule->last_coa = bule->coa;
-@@ -222,6 +239,7 @@ void bul_delete(struct bulentry *bule)
- if (!(bule->flags & IP6_MH_BU_HOME))
- mn_rr_delete_bule(bule);
- }
-+
- if (bule->flags & IP6_MH_BU_HOME) {
- if (bule->type == UNREACH_ENTRY) {
- pthread_mutex_lock(&hai->ha_list.c_lock);
-@@ -232,16 +250,28 @@ void bul_delete(struct bulentry *bule)
- } else {
- if (hai->home_block & HOME_LINK_BLOCK)
- xfrm_unblock_link(hai);
-+ if (bule->home_block & HOME_LINK_BLOCK)
-+ xfrm_unblock_bule_link(bule);
- if (hai->home_block & HOME_ADDR_BLOCK)
- xfrm_unblock_hoa(hai);
- if (hai->home_block & NEMO_RA_BLOCK)
- xfrm_unblock_ra(hai);
- if (hai->home_block & NEMO_FWD_BLOCK)
- xfrm_unblock_fwd(hai);
-+ if (bule->home_block & NEMO_FWD_BLOCK)
-+ bule_unblock_fwd(bule);
- }
- }
- while (bule->ext_cleanup)
- bule->ext_cleanup(bule);
-+
-+ /* MCoA
-+ * If MCoA is used, the tunnel related to this BULE
-+ * has to be deleted.
-+ */
-+ if (bule->home->reg_mcoa && bule->type != NON_MIP_CN_ENTRY)
-+ tunnel_del(bule->if_tunnel, NULL, NULL);
-+
- dbg("Deleting bule\n");
- dbg_func(bule, dump_bule);
- free_bule(bule);
-@@ -312,3 +342,129 @@ int bul_iterate(struct hash *h, int (* f
- struct hash *tmp = h ? h : &bul_hash;
- return hash_iterate(tmp, func, arg);
- }
-+
-+/**
-+ * bul_iterate_in - apply function to every BUL entry that match peer_addr
-+ * @peer_addr: the peer_addr of the hash
-+ * @func: function to apply
-+ * @arg: extra data for @func
-+ *
-+ * Iterates through binding update list, calling @func for each entry that
-+ * match peer_addr. Extra data may be passed to @func in @arg. @func
-+ * takes a BUL entry as its first argument and @arg as second argument.
-+ **/
-+int bul_iterate_in(struct in6_addr *peer_addr,
-+ int (* func)(void *, void *),
-+ void *arg)
-+{
-+ return hash_iterate_in(&bul_hash, peer_addr, func, arg);
-+}
-+
-+int bul_highest_priority(void *bule_v, void *best_bule_v)
-+{
-+ struct bulentry *bule = bule_v;
-+ struct bulentry **best_bule = best_bule_v;
-+
-+ assert(bule);
-+ assert(best_bule);
-+
-+ if(bule->type == NON_MIP_CN_ENTRY ||
-+ bule->type == UNREACH_ENTRY)
-+ return 0;
-+
-+ if (!(*best_bule)
-+ || (bule->priority > (*best_bule)->priority
-+ && bule->rules))
-+ (*best_bule) = bule;
-+
-+ return 0;
-+}
-+
-+int mcoa_bule_inc_counter(void *bule_v, void *counter_v)
-+{
-+ struct bulentry *bule = bule_v;
-+ int *counter = counter_v;
-+ assert(counter);
-+
-+ if(bule->type != NON_MIP_CN_ENTRY)
-+ (*counter)++;
-+ return 0;
-+}
-+
-+/**
-+ * mcoa_bule_count - count the number of entry (!NON_MIP_CN_ENTRY)
-+ * with the same peer_addr.
-+ * @bule: the bule where to pick up the peer address
-+ **/
-+
-+int mcoa_bule_count(struct bulentry *bule)
-+{
-+ int count = 0;
-+ assert(bule);
-+ bul_iterate_in(&bule->peer_addr, mcoa_bule_inc_counter, &count);
-+ return count;
-+}
-+
-+
-+int mcoa_bule_setdereg(void *bule_v, void *dereg_v)
-+{
-+ int *dereg = dereg_v;
-+ struct bulentry *bule = bule_v;
-+
-+ assert(dereg);
-+ bule->mcoa_dereg = *(dereg);
-+ return 0;
-+}
-+
-+/**
-+ * mcoa_bule_dereg - Set the BULE mcoa_dereg flag to value for
-+ * all entries that match bule->peer_addr.
-+ * @bule: the bule where to pick up the peer address
-+ * @value: the value to set
-+ **/
-+int mcoa_bule_dereg(struct bulentry *bule, int value)
-+{
-+ bul_iterate_in(&bule->peer_addr, mcoa_bule_setdereg, &value);
-+ return 0;
-+}
-+
-+/**
-+ * bule_block_fwd - Block forwarding for all MNPs
-+ * via the fwmark (BID) of the bule
-+ * @bule: the bule
-+ */
-+void bule_block_fwd(struct bulentry *bule)
-+{
-+ struct list_head *l;
-+ if (!bule->rules)
-+ return;
-+ bule->home_block |= NEMO_FWD_BLOCK;
-+ list_for_each(l, &bule->home->mob_net_prefixes) {
-+ struct prefix_list_entry *p = NULL;
-+ p = list_entry(l, struct prefix_list_entry, list);
-+ rule_add(NULL, 0, IP6_RULE_PRIO_MIP6_BLOCK,
-+ /*fwmark*/ bule->bid, RTN_BLACKHOLE,
-+ &p->ple_prefix, p->ple_plen,
-+ &in6addr_any, 0, 0);
-+ }
-+}
-+
-+/**
-+ * bule_unblock_fwd - unblock forwarding for all MNPs
-+ * via the fwmark (BID) of the bule
-+ * @bule: the bule
-+ */
-+void bule_unblock_fwd(struct bulentry *bule)
-+{
-+ struct list_head *l;
-+ bule->home_block &= ~NEMO_FWD_BLOCK;
-+ list_for_each(l, &bule->home->mob_net_prefixes) {
-+ struct prefix_list_entry *p = NULL;
-+ p = list_entry(l, struct prefix_list_entry, list);
-+ rule_del(NULL, 0, IP6_RULE_PRIO_MIP6_BLOCK,
-+ /*fwmark*/ bule->bid, RTN_BLACKHOLE,
-+ &p->ple_prefix, p->ple_plen,
-+ &in6addr_any, 0, 0);
-+ }
-+}
-+
-diff -r 82fcd4bea972 src/bul.h
---- a/src/bul.h Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/bul.h Fri Jan 11 17:02:25 2008 +0100
-@@ -9,6 +9,9 @@
- #include "tqueue.h"
- #include "hash.h"
- #include "list.h"
-+
-+#define BULE_TABLE_MIN 1
-+#define BULE_TABLE_MAX 251
-
- struct home_addr_info;
-
-@@ -31,10 +34,16 @@ struct bulentry {
- struct in6_addr hoa;
- struct in6_addr coa; /* care-of address of the sent BU */
- int if_coa;
-+ int if_tunnel; /* MCoA: Tunnel iface for the BCE */
-+ int table; /* MCoA: Routing table where are
-+ stored the routes */
-+ int rules; /* MCoA: if rules are installed for
-+ this BULE */
- int type; /* BUL / NON_MIP_CN / UNREACH */
- uint16_t seq; /* sequence number of the latest BU */
- uint16_t flags; /* BU send flags */
-- struct in6_addr last_coa; /* Last good coa */
-+ uint16_t bid; /* MCoA: Binding Identifier */
-+ struct in6_addr last_coa; /* Last good coa */
- struct timespec lastsent;
- struct timespec lifetime; /* lifetime sent in this BU */
- struct timespec delay; /* call back time in ms*/
-@@ -47,7 +56,11 @@ struct bulentry {
- uint8_t use_alt_coa; /* Whether to use alt. CoA option */
- uint8_t dereg; /* for calculating BSA key */
- uint8_t do_send_bu; /* send bu / not send bu */
--
-+ uint8_t priority; /* MCoA: BID priority */
-+ uint8_t home_block; /* MCoA: NEMO_FWD_BLOCK, ... */
-+ uint8_t mcoa_dereg; /* MCoA: if BCE needs to be
-+ deregistered with a BU */
-+
- /* Information for return routability */
- struct retrout_info rr;
- uint8_t Kbm[HMAC_SHA1_KEY_SIZE];
-@@ -84,7 +97,8 @@ enum {
-
- struct bulentry *bul_get(struct home_addr_info *hinfo,
- const struct in6_addr *our_addr,
-- const struct in6_addr *peer_addr);
-+ const struct in6_addr *peer_addr,
-+ u_int16_t bid);
-
- int bul_add(struct bulentry *bule);
-
-@@ -94,7 +108,11 @@ void bul_update_expire(struct bulentry *
- void bul_update_expire(struct bulentry *bule);
-
- int bul_iterate(struct hash *h, int (* func)(void *bule, void *arg), void *arg);
-+int bul_iterate_in(struct in6_addr *peer_addr,
-+ int (* func)(void *, void *),
-+ void *arg);
-
-+int bul_highest_priority(void *bule_v, void *best_bule_v);
- int bul_init(void);
- int bul_home_init(struct home_addr_info *home);
- void bul_home_cleanup(struct hash *bul);
-@@ -102,7 +120,12 @@ void bul_cleanup(void);
- void bul_cleanup(void);
- void dump_bule(void *bule, void *os);
- struct bulentry *create_bule(const struct in6_addr *hoa,
-- const struct in6_addr *cn_addr);
-+ const struct in6_addr *cn_addr,
-+ u_int16_t bid);
- void free_bule(struct bulentry *bule);
-+int mcoa_bule_count(struct bulentry *bule);
-+int mcoa_bule_dereg(struct bulentry *bule_v, int value);
-+void bule_block_fwd(struct bulentry *bule);
-+void bule_unblock_fwd(struct bulentry *bule);
-
- #endif
-diff -r 82fcd4bea972 src/cn.c
---- a/src/cn.c Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/cn.c Fri Jan 11 17:02:25 2008 +0100
-@@ -67,7 +67,11 @@ static void cn_recv_dst_unreach(const st
- if (icmp6_parse_data(ip6h, optlen, &laddr, &raddr) < 0)
- return;
-
-- bce = bcache_get(laddr, raddr);
-+ /* MCoA TODO2
-+ * Add MCoA support for the CN
-+ * MCOA_NO_BID must be replaced with the BUI's BID
-+ */
-+ bce = bcache_get(laddr, raddr, MCOA_NO_BID);
-
- if (bce == NULL)
- return;
-@@ -76,7 +80,7 @@ static void cn_recv_dst_unreach(const st
- if (bce->unreach > ICMP_ERROR_PERSISTENT_THRESHOLD &&
- bce->type != BCE_HOMEREG) {
- bcache_release_entry(bce);
-- bcache_delete(laddr, raddr);
-+ bcache_delete(laddr, raddr, MCOA_NO_BID);
- dbg("BCE for %x:%x:%x:%x:%x:%x:%x:%x deleted "
- "due to receipt of ICMPv6 destination unreach\n",
- NIP6ADDR(raddr));
-@@ -156,6 +160,7 @@ void cn_recv_bu(const struct ip6_mh *mh,
- struct in6_addr_bundle out;
- struct ip6_mh_binding_update *bu;
- struct ip6_mh_opt_nonce_index *non_ind;
-+ struct ip6_mh_opt_bid *bid_opt = NULL;
- struct bcentry *bce = NULL;
- struct timespec lft;
- int status, new = 0;
-@@ -175,7 +180,18 @@ void cn_recv_bu(const struct ip6_mh *mh,
-
- bu_flags = bu->ip6mhbu_flags;
- non_ind = mh_opt(&bu->ip6mhbu_hdr, &mh_opts, IP6_MHOPT_NONCEID);
-- bce = bcache_get(out.src, out.dst);
-+ /* MCoA TODO2
-+ * MCoA support for CN is not implemented yet
-+ * At the moment we ignore the BUs with BUI option
-+ */
-+ if ((bid_opt = mh_opt(&bu->ip6mhbu_hdr, &mh_opts, IP6_MHOPT_BID))) {
-+ dbg("Received BU with BUI sub-option, but CN doesn't "
-+ "support MCoA registration. BU skipped.\n");
-+ status = IP6_MH_BAS_REG_NOT_ALLOWED;
-+ goto send_nack;
-+ }
-+
-+ bce = bcache_get(out.src, out.dst, MCOA_NO_BID);
- if (bce) {
- if ((bce->flags^bu_flags) & (IP6_MH_BU_HOME|IP6_MH_BU_MR)) {
- /* H-bit or R-bit mismatch, flags changed */
-@@ -219,7 +235,7 @@ void cn_recv_bu(const struct ip6_mh *mh,
- goto send_nack;
- }
- /* else get rid of it */
-- bcache_delete(out.src, out.dst);
-+ bcache_delete(out.src, out.dst, MCOA_NO_BID);
- }
- } else {
- if (bu_flags & IP6_MH_BU_HOME) {
-@@ -281,18 +297,18 @@ void cn_recv_bu(const struct ip6_mh *mh,
- }
- /* dereg, success */
- bcache_release_entry(bce);
-- bcache_delete(out.src, out.dst);
-+ bcache_delete(out.src, out.dst, MCOA_NO_BID);
- status = IP6_MH_BAS_ACCEPTED;
- }
- if (bu_flags & IP6_MH_BU_ACK)
-- mh_send_ba(&out, status, 0, seqno, &lft, key, iif);
-+ mh_send_ba(&out, status, 0, seqno, &lft, 0, 0, key, iif);
- return;
- send_nack:
- if (bce) {
- bcache_release_entry(bce);
-- bcache_delete(out.src, out.dst);
-+ bcache_delete(out.src, out.dst, MCOA_NO_BID);
- }
-- mh_send_ba_err(&out, status, 0, seqno, pkey, iif);
-+ mh_send_ba_err(&out, status, 0, seqno, 0, 0, pkey, iif);
- }
-
- static struct mh_handler cn_bu_handler =
-diff -r 82fcd4bea972 src/conf.c
---- a/src/conf.c Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/conf.c Fri Jan 11 17:02:25 2008 +0100
-@@ -74,6 +74,7 @@ static void conf_version(void)
- {
- fprintf(stderr,
- "%s (%s) %s\n"
-+ "With Multiple Care-of Addresses registration support\n"
- "%s\n"
- "This is free software; see the source for copying conditions. There is NO\n"
- "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
-@@ -218,6 +219,7 @@ static void conf_default(struct mip6_con
-
- /* HA options */
- c->SendMobPfxAdvs = 1;
-+ c->HaAcceptMCoAReg = 0;
- c->SendUnsolMobPfxAdvs = 1;
- c->MaxMobPfxAdvInterval = 86400; /* seconds */
- c->MinMobPfxAdvInterval = 600; /* seconds */
-@@ -317,8 +319,89 @@ void conf_show(struct mip6_config *c)
- dbg("MinMobPfxAdvInterval = %u\n", c->MinMobPfxAdvInterval);
- dbg("HaMaxBindingLife = %u\n", c->HaMaxBindingLife);
- dbg("HaAcceptMobRtr = %s\n", CONF_BOOL_STR(c->HaAcceptMobRtr));
-+ dbg("HaAcceptMCoAReg = %s\n", CONF_BOOL_STR(c->HaAcceptMCoAReg));
-
- /* CN options */
- dbg("DoRouteOptimizationCN = %s\n",
- CONF_BOOL_STR(c->DoRouteOptimizationCN));
- }
-+
-+/*
-+ * get_reliable_from_ifindex - return the reliability value
-+ * from the interface index
-+ * @iif: the interface index
-+ */
-+int get_reliable_from_ifindex(int iif)
-+{
-+ struct list_head *list;
-+
-+ list_for_each(list, &conf.net_ifaces) {
-+ struct net_iface *nif;
-+ nif = list_entry(list, struct net_iface, list);
-+ if (nif->ifindex == iif) {
-+ if (is_if_mn(nif))
-+ return nif->mn_if_reliable;
-+ return -1;
-+ }
-+ }
-+ return -1;
-+}
-+
-+/*
-+ * get_bid_from_ifindex - return the bid from the interface index
-+ * @iif: the interface index
-+ */
-+uint16_t get_bid_from_ifindex(int iif)
-+{
-+ struct list_head *list;
-+
-+ list_for_each(list, &conf.net_ifaces) {
-+ struct net_iface *nif;
-+ nif = list_entry(list, struct net_iface, list);
-+ if (nif->ifindex == iif) {
-+ if (is_if_mn(nif))
-+ return nif->mn_if_bid;
-+ return 0;
-+ }
-+ }
-+ return 0;
-+}
-+
-+/*
-+ * get_prio_from_bid - return the priority from the bid
-+ * @bid: the bid of the interface
-+ */
-+uint8_t get_prio_from_bid(uint16_t bid)
-+{
-+ struct list_head *list;
-+
-+ list_for_each(list, &conf.net_ifaces) {
-+ struct net_iface *nif;
-+ nif = list_entry(list, struct net_iface, list);
-+ if (nif->mn_if_bid == bid) {
-+ if (is_if_mn(nif))
-+ return nif->mn_if_bidprio;
-+ return 0;
-+ }
-+ }
-+ return 0;
-+}
-+
-+/*
-+ * get_highest_prio - return the highest BID priority from the
-+ * interface list
-+ */
-+uint8_t get_highest_prio()
-+{
-+ struct list_head *list;
-+ int priority = 0;
-+
-+ list_for_each(list, &conf.net_ifaces) {
-+ struct net_iface *nif;
-+ nif = list_entry(list, struct net_iface, list);
-+ if (nif->mn_if_bidprio >= priority)
-+ priority = nif->mn_if_bidprio;
-+ }
-+ return priority;
-+}
-+
-diff -r 82fcd4bea972 src/conf.h
---- a/src/conf.h Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/conf.h Fri Jan 11 17:02:25 2008 +0100
-@@ -48,6 +48,7 @@ struct mip6_config {
-
- /* HA options */
- char HaAcceptMobRtr;
-+ char HaAcceptMCoAReg;
- char SendMobPfxAdvs;
- char SendUnsolMobPfxAdvs;
- unsigned int MaxMobPfxAdvInterval;
-@@ -66,6 +67,9 @@ struct net_iface {
- int is_rtr;
- int mip6_if_entity;
- int mn_if_preference;
-+ uint16_t mn_if_bid;
-+ uint8_t mn_if_bidprio;
-+ int mn_if_reliable;
- };
-
- extern struct mip6_config conf;
-@@ -119,6 +123,11 @@ int conf_parse(struct mip6_config *c, in
-
- void conf_show(struct mip6_config *c);
-
-+int get_reliable_from_ifindex(int iif);
-+uint16_t get_bid_from_ifindex(int iif);
-+uint8_t get_prio_from_bid(uint16_t bid);
-+uint8_t get_highest_prio();
-+
- int yyparse(void);
-
- int yylex(void);
-diff -r 82fcd4bea972 src/dhaad_mn.c
---- a/src/dhaad_mn.c Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/dhaad_mn.c Fri Jan 11 17:02:25 2008 +0100
-@@ -120,8 +120,9 @@ static void dhaad_resend(struct tq_elem
- pthread_rwlock_unlock(&mn_lock);
- return;
- }
-- t->dhaad_id = dhaad_send_request(hai->primary_coa.iif,
-- &hai->primary_coa.addr,
-+ assert(hai->current_coa);
-+ t->dhaad_id = dhaad_send_request(hai->current_coa->iif,
-+ &hai->current_coa->addr,
- &hai->home_prefix,
- hai->home_plen,
- hai->mob_rtr?
-@@ -146,8 +147,9 @@ static void _dhaad_start(struct home_add
- if (hai->mob_rtr && !(hai->home_block & NEMO_RA_BLOCK))
- xfrm_block_ra(hai);
- t->dhaad_resends = 0;
-- t->dhaad_id = dhaad_send_request(hai->primary_coa.iif,
-- &hai->primary_coa.addr,
-+ assert(hai->current_coa);
-+ t->dhaad_id = dhaad_send_request(hai->current_coa->iif,
-+ &hai->current_coa->addr,
- &hai->home_prefix,
- hai->home_plen,
- hai->mob_rtr?
-diff -r 82fcd4bea972 src/gram.y
---- a/src/gram.y Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/gram.y Fri Jan 11 17:02:25 2008 +0100
-@@ -47,15 +47,20 @@
- #include "util.h"
- #include "ipsec.h"
- #include "rtnl.h"
-+#include "bul.h"
-
- struct net_iface ni = {
- .mip6_if_entity = MIP6_ENTITY_NO,
- .mn_if_preference = POL_MN_IF_DEF_PREFERENCE,
-+ .mn_if_bid = POL_MN_IF_DEF_BID,
-+ .mn_if_bidprio = POL_MN_IF_DEF_BID_PRIORITY,
-+ .mn_if_reliable = POL_MN_IF_DEF_RELIABLE
- };
-
- struct home_addr_info hai = {
- .ro_policies = LIST_HEAD_INIT(hai.ro_policies),
-- .mob_net_prefixes = LIST_HEAD_INIT(hai.mob_net_prefixes)
-+ .mob_net_prefixes = LIST_HEAD_INIT(hai.mob_net_prefixes),
-+ .mcoa = LIST_HEAD_INIT(hai.mcoa)
- };
-
- LIST_HEAD(prefixes);
-@@ -185,6 +190,14 @@ static void uerror(const char *fmt, ...)
- %token ISMOBRTR
- %token HASERVEDPREFIX
- %token MOBRTRUSEEXPLICITMODE
-+%token HAACCEPTMCOAREG
-+%token MCOAREG
-+%token NOMCOAREG
-+%token BID
-+%token BIDPRIORITY
-+%token RELIABLE
-+%token REGMULTIPLECOA
-+%token IFMULTIPLECOA
-
- %token INV_TOKEN
-
-@@ -197,6 +210,7 @@ static void uerror(const char *fmt, ...)
- %type mnropolicyaddr
- %type dorouteopt
- %type bindaclpolval
-+%type mcoapolval
- %type prefixlen
- %type mip6entity
- %type xfrmaction
-@@ -306,6 +320,10 @@ topdef : MIP6ENTITY mip6entity ';'
- {
- conf.HaAcceptMobRtr = $2;
- }
-+ | HAACCEPTMCOAREG BOOL ';'
-+ {
-+ conf.HaAcceptMCoAReg = $2;
-+ }
- | HASERVEDPREFIX prefixlistentry ';'
- {
- list_splice(&prefixes,
-@@ -375,6 +393,9 @@ ifacedef : QSTRING ifacesub
- memset(&ni, 0, sizeof(struct net_iface));
- ni.mip6_if_entity = MIP6_ENTITY_NO;
- ni.mn_if_preference = POL_MN_IF_DEF_PREFERENCE;
-+ ni.mn_if_bid = POL_MN_IF_DEF_BID;
-+ ni.mn_if_bidprio = POL_MN_IF_DEF_BID_PRIORITY;
-+ ni.mn_if_reliable = POL_MN_IF_DEF_RELIABLE;
- }
- ;
-
-@@ -392,7 +413,44 @@ ifaceopt : IFTYPE mip6entity ';'
- }
- | MNIFPREFERENCE NUMBER ';'
- {
-- ni.mn_if_preference = $2;
-+ if (ni.mn_if_bid) {
-+ uerror("You cannot set MnIfPreference if BID "
-+ "is set. Use BidPriority instead.");
-+ return -1;
-+ }
-+ ni.mn_if_preference = $2;
-+ }
-+ | BID NUMBER ';'
-+ {
-+ if (ni.mn_if_preference) {
-+ uerror("If BID is set, you cannot set "
-+ "MnIfPreference. Use BidPriority instead.");
-+ return -1;
-+ }
-+ if ($2 < BULE_TABLE_MIN || $2 > BULE_TABLE_MAX) {
-+ uerror("BID error (%d <= Bid <= %d)",
-+ BULE_TABLE_MIN, BULE_TABLE_MAX);
-+ return -1;
-+ }
-+ ni.mn_if_bid = $2;
-+ }
-+ | BIDPRIORITY NUMBER ';'
-+ {
-+ if (ni.mn_if_preference) {
-+ uerror("You cannot set BidPriority if "
-+ "MnIfPreference is set.");
-+ return -1;
-+ }
-+ if ($2 < 1 || $2 > 255) {
-+ uerror("BidPriotity error "
-+ "(%d <= BidPriority <= %d)",1, 255);
-+ return -1;
-+ }
-+ ni.mn_if_bidprio = $2;
-+ }
-+ | RELIABLE BOOL ';'
-+ {
-+ ni.mn_if_reliable = $2;
- }
- ;
-
-@@ -432,15 +490,28 @@ linksub : QSTRING '{' linkdefs '}'
- INIT_LIST_HEAD(&nhai->ro_policies);
- INIT_LIST_HEAD(&nhai->ha_list.home_agents);
- INIT_LIST_HEAD(&nhai->mob_net_prefixes);
-+ INIT_LIST_HEAD(&nhai->mcoa);
- nhai->ha_list.dhaad_id = -1;
- list_splice(&hai.ro_policies, &nhai->ro_policies);
- list_splice(&hai.mob_net_prefixes,
- &nhai->mob_net_prefixes);
-+ list_splice(&hai.mcoa, &nhai->mcoa);
-+ if (!hai.reg_mcoa) {
-+ /* If MCoA registration is not used, we
-+ * initialize nhai->current_coa
-+ */
-+ nhai->current_coa = malloc(sizeof(struct mn_addr));
-+ if (nhai->current_coa == NULL) {
-+ uerror("out of memory");
-+ return -1;
-+ }
-+ }
- list_add_tail(&nhai->list, &conf.home_addrs);
-
- memset(&hai, 0, sizeof(struct home_addr_info));
- INIT_LIST_HEAD(&hai.ro_policies);
- INIT_LIST_HEAD(&hai.mob_net_prefixes);
-+ INIT_LIST_HEAD(&hai.mcoa);
- }
- ;
-
-@@ -468,6 +539,11 @@ linkdef : HOMEAGENTADDRESS ADDR ';'
- ipv6_addr_prefix(&hai.home_prefix, &$2, $4);
- hai.home_plen = $4;
- }
-+ | REGMULTIPLECOA BOOL ';'
-+ {
-+ hai.reg_mcoa = $2;
-+ }
-+ | IFMULTIPLECOA iflist ';'
- ;
-
- homeaddress : homeaddrdef prefixlistsub
-@@ -695,7 +771,12 @@ bindaclpolval : BOOL
- | NUMBER { $$ = $1; }
- ;
-
--bindaclpolicy : ADDR prefixlistsub bindaclpolval
-+mcoapolval : MCOAREG { $$ = 1; }
-+ | NOMCOAREG { $$ = 0; }
-+ | '' { $$ = 0; }
-+ ;
-+
-+bindaclpolicy : ADDR prefixlistsub mcoapolval bindaclpolval
- {
- bae = malloc(sizeof(struct policy_bind_acl_entry));
- if (bae == NULL) {
-@@ -707,7 +788,8 @@ bindaclpolicy : ADDR prefixlistsub binda
- bae->plen = 128;
- INIT_LIST_HEAD(&bae->mob_net_prefixes);
- bae->mnp_count = mv_prefixes(&bae->mob_net_prefixes);
-- bae->bind_policy = $3;
-+ bae->mcoa_reg = $3;
-+ bae->bind_policy = $4;
- list_add_tail(&bae->list, &conf.bind_acl);
- }
- ;
-@@ -745,4 +827,58 @@ prefixlistentry : ADDR '/' prefixlen
- list_add_tail(&p->list, &prefixes);
- }
- ;
-+
-+iflist : iflistentry
-+ | iflist ',' iflistentry
-+ ;
-+
-+iflistentry : QSTRING
-+ {
-+ struct mn_addr *mncoa;
-+ struct list_head *l;
-+ int declared = 0, bid = 0;
-+
-+ /* Check that this interface has been
-+ * previously declared as "Interface" */
-+ list_for_each(l, &conf.net_ifaces) {
-+ struct net_iface *ni;
-+ ni = list_entry(l, struct net_iface,
-+ list);
-+
-+ if(if_nametoindex($1) == ni->ifindex) {
-+ declared = 1;
-+ bid = ni->mn_if_bid;
-+ break;
-+ }
-+ }
-+
-+ if(!declared) {
-+ uerror("Interface %s has not been "
-+ "declared as Interface\n", $1);
-+ return -1;
-+ }
-+
-+ if(!bid) {
-+ uerror("Interface %s has no BID "
-+ "although you declared it in "
-+ "IfMultipleCoA\n", $1);
-+ return -1;
-+ }
-+
-+ mncoa = malloc(sizeof(struct mn_addr));
-+ if (mncoa == NULL) {
-+ fprintf(stderr, "%s: out of memory\n",
-+ __FUNCTION__);
-+ return -1;
-+ }
-+ memset(mncoa, 0, sizeof(struct mn_addr));
-+ if ((mncoa->iif = if_nametoindex($1)) == 0) {
-+ fprintf(stderr, "%s: %s is not a valid "
-+ "interface name\n", __FUNCTION__, $1);
-+ return -1;
-+ }
-+ free($1);
-+ list_add_tail(&mncoa->list, &hai.mcoa);
-+ }
-+ ;
- %%
-diff -r 82fcd4bea972 src/ha.c
---- a/src/ha.c Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/ha.c Fri Jan 11 17:02:25 2008 +0100
-@@ -59,6 +59,14 @@
- #include "xfrm.h"
- #include "ndisc.h"
- #include "prefix.h"
-+
-+#define HA_DEBUG_LEVEL 1
-+
-+#if HA_DEBUG_LEVEL >= 1
-+#define MDBG dbg
-+#else
-+#define MDBG(...)
-+#endif /* MDBG */
-
- static pthread_mutex_t bu_worker_mutex;
- static volatile unsigned long bu_worker_count = 0;
-@@ -504,7 +512,7 @@ static int ha_vt_init(void)
-
- static void nemo_ha_del_mnp_routes(struct list_head *old_mnps,
- struct list_head *new_mnps,
-- int ifindex, int all)
-+ int table, int ifindex, int all)
- {
- struct list_head *list;
- list_for_each(list, old_mnps) {
-@@ -514,14 +522,22 @@ static void nemo_ha_del_mnp_routes(struc
- prefix_list_find(new_mnps, &p->ple_prefix, p->ple_plen))
- continue;
-
-- route_del(ifindex, RT6_TABLE_MIP6, IP6_RT_PRIO_MIP6_FWD,
-+ route_del(ifindex, table, IP6_RT_PRIO_MIP6_FWD,
- NULL, 0, &p->ple_prefix, p->ple_plen, NULL);
-+
-+ /* MCoA
-+ * Delete the MNP fwmark rule
-+ */
-+ if(table != RT6_TABLE_MIP6)
-+ rule_del(NULL, table, IP6_RULE_PRIO_MIP6_FWD_FWM,
-+ table, RTN_UNICAST, &in6addr_any, 0,
-+ &p->ple_prefix, p->ple_plen, 0);
- }
- }
-
- static int nemo_ha_add_mnp_routes(struct list_head *old_mnps,
- struct list_head *new_mnps,
-- int ifindex, int all)
-+ int table, int ifindex, int all)
- {
- struct list_head *list;
- list_for_each(list, new_mnps) {
-@@ -530,11 +546,89 @@ static int nemo_ha_add_mnp_routes(struct
- if (!all &&
- prefix_list_find(old_mnps, &p->ple_prefix, p->ple_plen))
- continue;
-- if (route_add(ifindex, RT6_TABLE_MIP6, RTPROT_MIP,
-+ if (route_add(ifindex, table, RTPROT_MIP,
- 0, IP6_RT_PRIO_MIP6_FWD,
- NULL, 0, &p->ple_prefix, p->ple_plen, NULL) < 0)
- return -1;
-+ /* MCoA
-+ * Add the MNP fwmark rule
-+ */
-+ if(table != RT6_TABLE_MIP6
-+ && rule_add(NULL, table, IP6_RULE_PRIO_MIP6_FWD_FWM,
-+ table, RTN_UNICAST, &in6addr_any, 0,
-+ &p->ple_prefix, p->ple_plen, 0) < 0)
-+ return -1;
- }
-+ return 0;
-+}
-+
-+static int mcoa_ha_init_rt_table(struct bcentry *bce)
-+{
-+ /* MCoA TODO2
-+ * At the moment, the routing table number is the BID number.
-+ * BID thus must be between BCE_TABLE_MIN and BCE_TABLE_MAX
-+ */
-+ assert(bce);
-+
-+ /* If BID is not assigned, default table is taken */
-+ if (!bce->bid)
-+ return (bce->table = RT6_TABLE_MIP6);
-+
-+ if (bce->bid >= BCE_TABLE_MIN && bce->bid <= BCE_TABLE_MAX)
-+ return (bce->table = bce->bid);
-+
-+ return -1;
-+}
-+
-+static int mcoa_ha_del_dflt_rules(struct bcentry *bce)
-+{
-+ struct list_head *list;
-+ struct prefix_list_entry *pfx;
-+ struct bcentry *best_bce = bce;
-+ const struct in6_addr *peer_addr = &bce->peer_addr;
-+ int8_t priority = 0;
-+
-+ MDBG("Current BCE has the best priority (%d), "
-+ "erasing default rules\n", best_bce->priority);
-+
-+ /* Erase the default HoA rule */
-+ rule_del(NULL, 0, IP6_RULE_PRIO_MIP6_FWD_MCOA, 0,
-+ RTN_UNICAST, &in6addr_any, 0, peer_addr, 128, 0);
-+
-+ /* Erase the default MNP rules */
-+ list_for_each(list, &bce->mob_net_prefixes) {
-+ pfx = list_entry(list, struct prefix_list_entry, list);
-+ rule_del(NULL, 0, IP6_RULE_PRIO_MIP6_FWD_MCOA, 0,
-+ RTN_UNICAST, &in6addr_any, 0,
-+ &pfx->ple_prefix, pfx->ple_plen, 0);
-+ }
-+
-+ /* Create new rule with next best bce available */
-+ priority = bce->priority;
-+ bce->priority = 0;
-+ bcache_iterate_in(&bce->peer_addr, bce_highest_priority,
-+ &best_bce);
-+ bce->priority = priority;
-+
-+ if(best_bce != bce) {
-+ MDBG("Rules replaced with BCE prio %d\n",
-+ best_bce->priority);
-+ rule_add(NULL, best_bce->table,
-+ IP6_RULE_PRIO_MIP6_FWD_MCOA, 0, RTN_UNICAST,
-+ &in6addr_any, 0, peer_addr, 128, 0);
-+
-+ /* Default prefix rules */
-+ list_for_each(list, &bce->mob_net_prefixes) {
-+ pfx = list_entry(list,
-+ struct prefix_list_entry, list);
-+ rule_add(NULL, best_bce->table,
-+ IP6_RULE_PRIO_MIP6_FWD_MCOA, 0,
-+ RTN_UNICAST, &in6addr_any, 0,
-+ &pfx->ple_prefix, pfx->ple_plen, 0);
-+ }
-+ } else
-+ MDBG("No other BCE available, no dflt rules added\n");
-+
- return 0;
- }
-
-@@ -544,10 +638,49 @@ struct home_tnl_ops_parm {
- struct list_head mob_net_prefixes;
- };
-
-+static int mcoa_ha_add_dflt_rules(struct home_tnl_ops_parm *p)
-+{
-+ struct list_head *list;
-+ struct bcentry *bce = p->bce;
-+ const struct in6_addr *peer_addr = &bce->peer_addr;
-+
-+ MDBG("BCE has the best priority (%d), adding default HoA "
-+ "and prefix rules\n", bce->priority);
-+
-+ /* Erase the default HoA rule */
-+ rule_del(NULL, 0, IP6_RULE_PRIO_MIP6_FWD_MCOA, 0,
-+ RTN_UNICAST, &in6addr_any, 0, peer_addr, 128, 0);
-+
-+ /* Add the default HoA rule */
-+ if (rule_add(NULL, bce->table,
-+ IP6_RULE_PRIO_MIP6_FWD_MCOA, 0, RTN_UNICAST,
-+ &in6addr_any, 0, peer_addr, 128, 0) < 0)
-+ return -1;
-+
-+ /* Delete and add the default prefix rules */
-+ list_for_each(list, &p->mob_net_prefixes) {
-+ struct prefix_list_entry *pfx;
-+ pfx = list_entry(list, struct prefix_list_entry, list);
-+
-+ rule_del(NULL, 0, IP6_RULE_PRIO_MIP6_FWD_MCOA,
-+ 0, RTN_UNICAST, &in6addr_any, 0,
-+ &pfx->ple_prefix, pfx->ple_plen, 0);
-+
-+ if (rule_add(NULL, bce->table,
-+ IP6_RULE_PRIO_MIP6_FWD_MCOA, 0,
-+ RTN_UNICAST, &in6addr_any, 0,
-+ &pfx->ple_prefix, pfx->ple_plen, 0) < 0)
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
- static int home_tnl_del(int old_if, int new_if, struct home_tnl_ops_parm *p)
- {
- const struct in6_addr *our_addr, *peer_addr, *coa, *old_coa;
- struct list_head *mnp;
-+ struct bcentry *best_bce = NULL;
-
- assert(old_if);
-
-@@ -565,12 +698,33 @@ static int home_tnl_del(int old_if, int
- ha_ipsec_tnl_pol_del(our_addr, peer_addr, p->bce->tunnel, mnp);
- }
- /* delete HoA route */
-+ /* MCoA: The route is deleted in the table given by p->bce->table */
-+ /* RKRK: for the moment the route is installed in the MAIN table.
-+ * See home_tnl_add */
-+ //MDBG("Deleting old default route in table %d\n", p->bce->table);
-+ MDBG("Deleting old default route in table %d\n", RT6_TABLE_MAIN);
-+ //route_del(old_if, p->bce->table,
- route_del(old_if, RT6_TABLE_MAIN,
- IP6_RT_PRIO_MIP6_FWD, NULL, 0, peer_addr, 128, NULL);
--
-+
- /* delete MNP routes */
- nemo_ha_del_mnp_routes(&p->bce->mob_net_prefixes,
-- &p->mob_net_prefixes, old_if, 1);
-+ &p->mob_net_prefixes, p->bce->table,
-+ old_if, 1);
-+ /* MCoA
-+ * Delete the HoA and fwmark rules, and if needed replace
-+ * the default HoA and MNP rules with the best available one
-+ */
-+ if(p->bce->table != RT6_TABLE_MIP6) {
-+ rule_del(NULL, p->bce->table, IP6_RULE_PRIO_MIP6_FWD_FWM,
-+ p->bce->table, RTN_UNICAST, &in6addr_any, 0,
-+ peer_addr, 128, 0);
-+ best_bce = p->bce;
-+ bcache_iterate_in(&p->bce->peer_addr,
-+ bce_highest_priority, &best_bce);
-+ if(best_bce == p->bce)
-+ mcoa_ha_del_dflt_rules(p->bce);
-+ }
- /* update tunnel interface */
- p->bce->tunnel = new_if;
-
-@@ -581,6 +735,7 @@ static int home_tnl_add(int old_if, int
- {
- const struct in6_addr *our_addr, *peer_addr, *coa, *old_coa;
- struct list_head *mnp;
-+ struct bcentry *best_bce = NULL;
-
- assert(new_if);
-
-@@ -596,7 +751,8 @@ static int home_tnl_add(int old_if, int
-
- /* add MNP routes */
- if (nemo_ha_add_mnp_routes(&p->bce->mob_net_prefixes,
-- &p->mob_net_prefixes, new_if, 1) < 0) {
-+ &p->mob_net_prefixes, p->bce->table,
-+ new_if, 1) < 0) {
- if (p->bce->nemo_type == BCE_NEMO_EXPLICIT)
- p->ba_status = IP6_MH_BAS_INVAL_PRFX;
- else
-@@ -604,11 +760,38 @@ static int home_tnl_add(int old_if, int
- goto err;
- }
- /* add HoA route */
-+ /* MCoA: The route is added in the table given by p->bce->table */
-+ /* RKRK: does not work. Route has to be added in the MAIN table.
-+ * Need to check why! */
-+ //MDBG("Adding route in table %d via iface %d\n", p->bce->table, new_if);
-+ MDBG("Adding route in table %d via iface %d\n", RT6_TABLE_MAIN, new_if);
-+ //if (route_add(new_if, p->bce->table,
- if (route_add(new_if, RT6_TABLE_MAIN,
- RTPROT_MIP, 0, IP6_RT_PRIO_MIP6_FWD,
- NULL, 0, peer_addr, 128, NULL) < 0) {
- p->ba_status = IP6_MH_BAS_INSUFFICIENT;
- goto err;
-+ }
-+ /* MCoA
-+ * Add the HoA and fwmark rules, and if needed replace
-+ * the default HoA and MNP rules with the best available one
-+ */
-+ if (p->bce->table != RT6_TABLE_MIP6) {
-+ if (rule_add(NULL, p->bce->table,
-+ IP6_RULE_PRIO_MIP6_FWD_FWM,
-+ p->bce->table, RTN_UNICAST,
-+ &in6addr_any, 0, peer_addr, 128, 0) < 0) {
-+ p->ba_status = IP6_MH_BAS_INSUFFICIENT;
-+ goto err;
-+ }
-+ best_bce = p->bce;
-+ bcache_iterate_in(&p->bce->peer_addr,
-+ bce_highest_priority, &best_bce);
-+ if(best_bce == p->bce
-+ && mcoa_ha_add_dflt_rules(p) < 0) {
-+ p->ba_status = IP6_MH_BAS_INSUFFICIENT;
-+ goto err;
-+ }
- }
- /* add SP entry */
- if (conf.UseMnHaIPsec) {
-@@ -664,9 +847,11 @@ static int home_tnl_chg(int old_if, int
- /* Do the same for routes */
- nemo_ha_del_mnp_routes(&p->bce->mob_net_prefixes,
- &p->mob_net_prefixes,
-+ p->bce->table,
- old_if, 0);
- if (nemo_ha_add_mnp_routes(&p->bce->mob_net_prefixes,
- &p->mob_net_prefixes,
-+ p->bce->table,
- new_if, 0) < 0) {
- if (p->bce->nemo_type == BCE_NEMO_EXPLICIT)
- p->ba_status = IP6_MH_BAS_INVAL_PRFX;
-@@ -707,12 +892,22 @@ static int home_tnl_ops(int request, int
-
- static void home_cleanup(struct bcentry *bce)
- {
-- mpd_cancel_mpa(&bce->our_addr, &bce->peer_addr);
-+ int nb_entry = mcoa_bce_count(&bce->peer_addr);
-+
-+ /* MCoA
-+ * MPA is canceled if this is the last BCE entry
-+ */
-+ if (nb_entry == 1)
-+ mpd_cancel_mpa(&bce->our_addr, &bce->peer_addr);
-
- if (bce->link > 0) {
-- route_del(bce->link, RT6_TABLE_MIP6, IP6_RT_PRIO_MIP6_OUT,
-+ route_del(bce->link, bce->table, IP6_RT_PRIO_MIP6_OUT,
- &bce->our_addr, 128, &bce->peer_addr, 128, NULL);
-- proxy_nd_stop(bce->link, &bce->peer_addr, bce->flags);
-+ /* MCoA
-+ * Proxy ND is stopped if this is the last BCE entry
-+ */
-+ if (nb_entry == 1)
-+ proxy_nd_stop(bce->link, &bce->peer_addr, bce->flags);
- }
- if (bce->tunnel > 0) {
- struct home_tnl_ops_parm p = {
-@@ -724,6 +919,9 @@ static void home_cleanup(struct bcentry
- if (conf.UseMnHaIPsec) {
- ha_mn_ipsec_pol_mod(&bce->our_addr, &bce->peer_addr);
- }
-+
-+ /* MCoA: Freeing the BCE's MNPs list */
-+ prefix_list_free(&bce->mob_net_prefixes);
- }
-
-
-@@ -800,19 +998,28 @@ static void *ha_recv_bu_worker(void *var
- {
- struct ha_recv_bu_args *arg = varg;
- struct in6_addr_bundle out;
-- struct bcentry *bce;
-+ struct bcentry *bce, *bce_exists;
- struct timespec lft, tmp;
-- int iif, status, new, home_ifindex;
-- uint16_t bu_flags, seqno;
-- uint8_t ba_flags;
-+ int iif, status, status_bid, new, home_ifindex;
-+ int update_dflt_table;
-+ uint16_t bu_flags, seqno, bid;
-+ uint8_t ba_flags, bid_priority, bid_flags;
- struct home_tnl_ops_parm p;
-+ struct ip6_mh_opt_bid *bid_opt;
-
- pthread_dbg("thread started");
- restart:
- home_ifindex = 0;
- new = 0;
-+ bid = 0;
-+ bid_priority = 0;
-+ bid_flags = 0;
-+ update_dflt_table = 0;
- ba_flags = 0;
-- lft = arg->lft;
-+ status = IP6_MH_BAS_UNSPECIFIED;
-+ status_bid = 0;
-+ bce = NULL;
-+ lft = arg->lft;
- iif = arg->iif;
- bu_flags = arg->bu->ip6mhbu_flags;
- seqno = ntohs(arg->bu->ip6mhbu_seqno);
-@@ -827,8 +1034,79 @@ restart:
- else
- out.bind_coa = NULL;
- out.local_coa = NULL;
-+ bid_opt = NULL;
-
-- bce = bcache_get(out.src, out.dst);
-+ /* MCoA
-+ * We check if a BCE already exists for this HoA
-+ * We take the first one available
-+ */
-+ bce_exists = bcache_get(out.src, out.dst, MCOA_NO_BID);
-+ if(bce_exists)
-+ bcache_release_entry(bce_exists);
-+
-+ /* MCoA
-+ * we need the BID before looking at the BCE
-+ */
-+ bid_opt = mh_opt(&arg->bu->ip6mhbu_hdr,
-+ &arg->mh_opts,
-+ IP6_MHOPT_BID);
-+
-+ if (bid_opt && !default_mcoa_reg(out.dst)) {
-+ /* MCoA: BAck without BID option will be sent */
-+ MDBG("BUI option, but MCoA registration not allowed.\n");
-+ } else if (bid_opt) {
-+ MDBG("BUI option, and HA is configured for MCoA.\n");
-+ bid = ntohs(bid_opt->ip6mobid_bid);
-+ bid_priority = bid_opt->ip6mobid_priority;
-+ bid_flags = ntohs(bid_opt->ip6mobid_reserved);
-+
-+ if (!bid) {
-+ MDBG("BID invalid, BU discarded.\n");
-+ goto out;
-+ }
-+
-+ MDBG("BID = %d, Priority = %d\n", bid, bid_priority);
-+ /* MCoA TODO1
-+ * if B flag is set but no altcoa option:
-+ * BAck status 145.
-+ * To update according to latest draft.
-+ */
-+ if (bid_flags & IP6_OPT_BID_BULK) {
-+ /* MCoA TODO1
-+ * At the moment we do not check the AltCoA option,
-+ * and just reject the BU if B flag is set
-+ */
-+ MDBG("BULK Reg., but not supported yet.\n");
-+ status = IP6_MH_BAS_MCOA_BULK_FAILED;
-+ goto send_nack;
-+ }
-+ if (bce_exists && !bce_exists->bid) {
-+ /* MCoA
-+ * The BCE has a BID = 0, this means no MCoA
-+ * are registered. We delete the entry and set
-+ * BA status to 144.
-+ * New registratration is done later
-+ */
-+ MDBG("BID option but BCE has no BID\n");
-+ MDBG("Delete BCE and register new one.\n");
-+ bcache_delete(out.src, out.dst, MCOA_NO_BID);
-+ status_bid = IP6_MH_BAS_CONFLICT_BINDING;
-+ }
-+ } else /* No BUI option in BU */ {
-+ if(tsisset(lft) && bce_exists && bce_exists->bid) {
-+ /* MCoA
-+ * A BCE exists with a BID != 0 but no BUI
-+ * sub-option are set in the BU: we delete
-+ * all existing entries for this HoA. New
-+ * registration is done later.
-+ */
-+ MDBG("No BID option but BCE has BID.\n");
-+ MDBG("Delete all BCE and register new one.\n");
-+ bcache_delete(out.src, out.dst, MCOA_NO_BID);
-+ }
-+ }
-+
-+ bce = bcache_get(out.src, out.dst, bid);
- if (bce) {
- if (bce->type != BCE_NONCE_BLOCK) {
- /* H-bit or R-bit mismatch, flags changed */
-@@ -873,7 +1151,7 @@ restart:
- goto send_nack;
- }
- /* else get rid of it */
-- bcache_delete(out.src, out.dst);
-+ bcache_delete(out.src, out.dst, bid);
- }
- } else if (!tsisset(lft)) {
- status = IP6_MH_BAS_NOT_HA;
-@@ -895,6 +1173,10 @@ restart:
- out.src, arg->bu, arg->len);
- if (status >= IP6_MH_BAS_UNSPECIFIED)
- goto send_nack;
-+
-+ if(status_bid)
-+ status = status_bid;
-+
- /* lifetime may be further decreased by local policy */
- if (conf.pmgr.max_binding_life(out.dst, out.bind_coa, out.src,
- arg->bu, arg->len, &lft, &tmp)) {
-@@ -916,24 +1198,38 @@ restart:
- bce->type = BCE_DAD;
- bce->cleanup = NULL;
- bce->link = home_ifindex;
--
-+ bce->bid = bid;
-+ bce->priority = bid_priority;
-+ if(bce_exists)
-+ bce->xfrm_create = 0;
-+ else
-+ bce->xfrm_create = 1;
-+
-+ /* MCoA: Initialize the routing table used by the BCE */
-+ if(mcoa_ha_init_rt_table(bce) < 0) {
-+ free(bce);
-+ bce = NULL;
-+ status = IP6_MH_BAS_INSUFFICIENT;
-+ goto send_nack;
-+ }
- if (bcache_add_homereg(bce) < 0) {
- free(bce);
- bce = NULL;
- status = IP6_MH_BAS_INSUFFICIENT;
- goto send_nack;
- }
-- if (!(arg->flags & HA_BU_F_SKIP_DAD)) {
-+ /* MCoA: Do DAD only if no entries yet for this HoA */
-+ if (!(arg->flags & HA_BU_F_SKIP_DAD) && !bce_exists) {
- /* Do DAD for home address */
- if (ndisc_do_dad(home_ifindex, out.dst,
- bu_flags & IP6_MH_BU_LLOCAL) < 0) {
-- bcache_delete(out.src, out.dst);
-+ bcache_delete(out.src, out.dst, bid);
- bce = NULL;
- status = IP6_MH_BAS_DAD_FAILED;
- goto send_nack;
- }
- }
-- bce = bcache_get(out.src, out.dst);
-+ bce = bcache_get(out.src, out.dst, bid);
- if (!bce) {
- BUG("BCE deleted before DAD completed!");
- status = IP6_MH_BAS_UNSPECIFIED;
-@@ -965,6 +1261,7 @@ restart:
- bce->seqno = seqno;
- bce->flags = bu_flags;
- bce->lifetime = lft;
-+
- if (new) {
- if (tunnel_add(out.src, out.bind_coa, 0,
- home_tnl_ops, &p) < 0) {
-@@ -979,7 +1276,8 @@ restart:
-
- bce->cleanup = home_cleanup;
-
-- if (route_add(bce->link, RT6_TABLE_MIP6,
-+ /* MCoA: The route is added in the table given by the BCE */
-+ if (route_add(bce->link, bce->table,
- RTPROT_MIP, 0, IP6_RT_PRIO_MIP6_OUT,
- &bce->our_addr, 128, &bce->peer_addr, 128,
- NULL) < 0) {
-@@ -987,16 +1285,23 @@ restart:
- goto send_nack;
- }
-
-- if (proxy_nd_start(bce->link, out.dst, out.src,
-- bu_flags) < 0) {
-- status = IP6_MH_BAS_INSUFFICIENT;
-- goto send_nack;
-+ /* MCoA: Do Proxy ND only if no entries yet for this HoA */
-+ if (!bce_exists) {
-+ if (proxy_nd_start(bce->link, out.dst,
-+ out.src, bu_flags) < 0) {
-+ status = IP6_MH_BAS_INSUFFICIENT;
-+ goto send_nack;
-+ }
- }
- bce->type = BCE_HOMEREG;
- bcache_complete_homereg(bce);
- } else {
- bce->old_coa = bce->coa;
- bce->coa = *out.bind_coa;
-+ if (tsisset(lft)) {
-+ bce->bid = bid;
-+ bce->priority = bid_priority;
-+ }
- if (tunnel_mod(bce->tunnel, out.src, out.bind_coa, 0,
- home_tnl_ops, &p) < 0) {
- if (p.ba_status >= IP6_MH_BAS_UNSPECIFIED)
-@@ -1006,15 +1311,24 @@ restart:
- goto send_nack;
- }
- /* Now update the MNP list in the BCE */
-- prefix_list_free(&bce->mob_net_prefixes);
-- list_splice(&p.mob_net_prefixes, &bce->mob_net_prefixes);
--
-+ /* MCoA: the update is done only if this is not a
-+ * deregistration BU, otherwise MNPs are erased from the BCE
-+ * (the dereg BU does not have any MNP option), thus there
-+ * is a problem to update the fwmark MNP rules
-+ */
-+ if (tsisset(lft)) {
-+ prefix_list_free(&bce->mob_net_prefixes);
-+ list_splice(&p.mob_net_prefixes, &bce->mob_net_prefixes);
-+ }
- bcache_update_expire(bce);
- }
- /* bce is always valid here */
- bcache_release_entry(bce);
- if (!tsisset(lft))
-- bcache_delete(out.src, out.dst);
-+ /* MCoA: We delete one specific entry (bid is set)
-+ * or all entries for this HoA (if bid is set to 0)
-+ */
-+ bcache_delete(out.src, out.dst, bid);
-
- if ((bu_flags & IP6_MH_BU_KEYM) &&
- conf.pmgr.use_keymgm(out.dst, out.src))
-@@ -1035,12 +1349,16 @@ restart:
- * have a binding before sending this Binding Update,
- * discard the connections to the home address. */
- }
-- if (status < IP6_MH_BAS_UNSPECIFIED && bu_flags & IP6_MH_BU_MR)
-+ if ((status < IP6_MH_BAS_UNSPECIFIED
-+ || status == IP6_MH_BAS_CONFLICT_BINDING)
-+ && bu_flags & IP6_MH_BU_MR)
- ba_flags |= IP6_MH_BA_MR;
-
- if (!(arg->flags & HA_BU_F_SKIP_BA))
-- mh_send_ba(&out, status, ba_flags, seqno, &lft, NULL, iif);
-- if (new && tsisset(lft))
-+ mh_send_ba(&out, status, ba_flags, seqno, &lft,
-+ bid, bid_priority, NULL, iif);
-+ /* MCoA: Start MPA only if no entries yet for this HoA */
-+ if (!bce_exists && new && tsisset(lft))
- mpd_start_mpa(&bce->our_addr, &bce->peer_addr);
- out:
- free(arg);
-@@ -1060,10 +1378,12 @@ send_nack:
- send_nack:
- if (bce) {
- bcache_release_entry(bce);
-- bcache_delete(out.src, out.dst);
-+ bcache_delete(out.src, out.dst, bid);
- }
- if (!(arg->flags & HA_BU_F_SKIP_BA))
-- mh_send_ba_err(&out, status, 0, seqno, NULL, iif);
-+ /* MCoA: Specify the BID and BID priority to the BAck */
-+ mh_send_ba_err(&out, status, 0, seqno, bid,
-+ bid_priority, NULL, iif);
- goto out;
- }
-
-@@ -1089,12 +1409,13 @@ int ha_recv_bu_main(const struct ip6_mh
-
- arg = malloc(sizeof(struct ha_recv_bu_args) + len);
- if (!arg) {
-- if (bce_exists(out.src, out.dst))
-- bcache_delete(out.src, out.dst);
-+ if (bce_exists(out.src, out.dst, MCOA_NO_BID))
-+ bcache_delete(out.src, out.dst, MCOA_NO_BID);
-
- if (!(arg->flags & HA_BU_F_SKIP_BA))
- mh_send_ba_err(&out, IP6_MH_BAS_INSUFFICIENT, 0,
-- ntohs(bu->ip6mhbu_seqno), NULL, iif);
-+ ntohs(bu->ip6mhbu_seqno), 0, 0,
-+ NULL, iif);
- return -ENOMEM;
- }
- arg->src = *out.src;
-@@ -1166,8 +1487,9 @@ int ha_init(void)
- return -1;
- if (mpd_ha_init() < 0)
- return -1;
-+ /* MCoA: Rule to the default table (RT6_TABLE_MIP6) */
- if (rule_add(NULL, RT6_TABLE_MIP6,
-- IP6_RULE_PRIO_MIP6_FWD, RTN_UNICAST,
-+ IP6_RULE_PRIO_MIP6_FWD, 0, RTN_UNICAST,
- &in6addr_any, 0, &in6addr_any, 0, 0) < 0)
- return -1;
- icmp6_handler_reg(ND_ROUTER_ADVERT, &ha_ra_handler);
-@@ -1185,7 +1507,7 @@ void ha_cleanup(void)
- pthread_mutex_unlock(&bu_worker_mutex);
- bcache_flush();
- rule_del(NULL, RT6_TABLE_MIP6,
-- IP6_RULE_PRIO_MIP6_FWD, RTN_UNICAST,
-+ IP6_RULE_PRIO_MIP6_FWD, 0, RTN_UNICAST,
- &in6addr_any, 0, &in6addr_any, 0, 0);
- mpd_ha_cleanup();
- dhaad_ha_cleanup();
-diff -r 82fcd4bea972 src/hash.c
---- a/src/hash.c Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/hash.c Fri Jan 11 17:02:25 2008 +0100
-@@ -47,6 +47,7 @@ struct hash_entry {
- struct hash_entry {
- struct in6_addr *our_addr; /* pointer to our_addr in data */
- struct in6_addr *peer_addr; /* pointer to peer_addr in data */
-+ uint16_t *bid; /* pointer to bid in data, can be NULL */
- struct hash_entry *next;
- void *data;
- };
-@@ -78,7 +79,7 @@ static uint32_t calc_hash1(int s, const
- }
-
- static int match2(struct hash_entry *h, const struct in6_addr *our_addr,
-- const struct in6_addr *peer_addr)
-+ const struct in6_addr *peer_addr, uint16_t bid)
- {
- assert(h);
- assert(our_addr && h->our_addr);
-@@ -89,9 +90,15 @@ static int match2(struct hash_entry *h,
- printf("h->peer %s\n", inet_ntop(AF_INET6, h->peer_addr, s, sizeof(s)));
- printf("our_addr %s\n", inet_ntop(AF_INET6, our_addr, s, sizeof(s)));
- printf("h->our_addr %s\n", inet_ntop(AF_INET6, h->our_addr, s, sizeof(s)));
-+ printf("bid %d\n", bid);
-+ if(h->bid != NULL)
-+ printf("h->bid %d\n", *(h->bid));
-+ else
-+ printf("h->bid is NULL\n");
- #endif
- if (IN6_ARE_ADDR_EQUAL(h->peer_addr, peer_addr) &&
-- IN6_ARE_ADDR_EQUAL(h->our_addr, our_addr)) {
-+ IN6_ARE_ADDR_EQUAL(h->our_addr, our_addr) &&
-+ (bid == 0 || (h->bid != NULL && bid == *(h->bid)))) {
- return 1;
- }
- return 0;
-@@ -99,7 +106,7 @@ static int match2(struct hash_entry *h,
- }
-
- static int match1(struct hash_entry *h, const struct in6_addr *dummy,
-- const struct in6_addr *peer_addr)
-+ const struct in6_addr *peer_addr, uint16_t bid)
- {
- assert(h);
- assert(h->peer_addr && peer_addr);
-@@ -107,8 +114,14 @@ static int match1(struct hash_entry *h,
- char s[INET6_ADDRSTRLEN];
- printf("match1: peer %s\n", inet_ntop(AF_INET6, peer_addr, s, sizeof(s)));
- printf("h->peer %s\n", inet_ntop(AF_INET6, h->peer_addr, s, sizeof(s)));
-+ printf("bid %d\n", bid);
-+ if(h->bid != NULL)
-+ printf("h->bid %d\n", *(h->bid));
-+ else
-+ printf("h->bid is NULL\n");
- #endif
-- if (!IN6_ARE_ADDR_EQUAL(h->peer_addr, peer_addr))
-+ if (!IN6_ARE_ADDR_EQUAL(h->peer_addr, peer_addr) ||
-+ (bid !=0 && h->bid != NULL && bid != *(h->bid)))
- return 0;
- return 1;
- }
-@@ -155,7 +168,8 @@ void hash_cleanup(struct hash *h)
-
- void *hash_get(const struct hash *h,
- const struct in6_addr *our_addr,
-- const struct in6_addr *peer_addr)
-+ const struct in6_addr *peer_addr,
-+ uint16_t bid)
- {
- struct hash_entry *hptr = NULL;
-
-@@ -165,7 +179,7 @@ void *hash_get(const struct hash *h,
- hptr = h->hash_buckets[h->calc_hash(h->buckets, our_addr , peer_addr)];
-
- while(hptr) {
-- if (h->match(hptr, our_addr, peer_addr))
-+ if (h->match(hptr, our_addr, peer_addr, bid))
- return hptr->data;
- hptr = hptr->next;
- }
-@@ -173,7 +187,8 @@ void *hash_get(const struct hash *h,
- }
-
- int hash_add(const struct hash *h, void *data,
-- struct in6_addr *our_addr, struct in6_addr *peer_addr)
-+ struct in6_addr *our_addr, struct in6_addr *peer_addr,
-+ uint16_t *bid)
- {
- struct hash_entry *hptr = NULL, *new;
- uint32_t hash_ind;
-@@ -185,17 +200,19 @@ int hash_add(const struct hash *h, void
- assert(peer_addr);
-
- if ((new = (struct hash_entry *)malloc(sizeof(struct hash_entry))) == NULL) {
-- dbg("out of memeory\n");
-+ dbg("out of memory\n");
- return -ENOMEM;
- }
- new->our_addr = our_addr;
- new->peer_addr = peer_addr;
- new->data = data;
-+ new->bid = bid;
- hash_ind = h->calc_hash(h->buckets, our_addr, peer_addr);
- hptr = h->hash_buckets[hash_ind];
- if (hptr) {
- while (hptr->next){
-- if (h->match(hptr, our_addr, peer_addr)) {
-+ if (h->match(hptr, our_addr, peer_addr,
-+ (bid) ? (*bid) : 0)) {
- free(new);
- return -EEXIST;
- }
-@@ -231,9 +248,35 @@ int hash_iterate(const struct hash *h, i
- return 0;
- }
-
-+int hash_iterate_in(const struct hash *h,
-+ const struct in6_addr *peer_addr,
-+ int (*func)(void *, void *),
-+ void *arg)
-+{
-+ int err = 0;
-+ int i;
-+ struct hash_entry *hptr, *nptr;
-+
-+ assert(func);
-+
-+ for (i=0; i < h->buckets; i++) {
-+ if((hptr = h->hash_buckets[i]) != NULL) {
-+ while(hptr) {
-+ nptr = hptr->next;
-+ if (IN6_ARE_ADDR_EQUAL(hptr->peer_addr, peer_addr)
-+ && (err = func(hptr->data, arg)))
-+ return err;
-+ hptr = nptr;
-+ }
-+ }
-+ }
-+ return 0;
-+}
-+
- void hash_delete(const struct hash *h,
- const struct in6_addr *our_addr,
-- const struct in6_addr *peer_addr)
-+ const struct in6_addr *peer_addr,
-+ uint16_t bid)
- {
- struct hash_entry *hptr, *pptr, *head;
- int hash_ind;
-@@ -247,7 +290,7 @@ void hash_delete(const struct hash *h,
-
- pptr = hptr = head;
- while (hptr) {
-- if (h->match(hptr, our_addr, peer_addr)){
-+ if (h->match(hptr, our_addr, peer_addr, bid)){
- if (hptr != head)
- pptr->next = hptr->next;
- else {
-diff -r 82fcd4bea972 src/hash.h
---- a/src/hash.h Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/hash.h Fri Jan 11 17:02:25 2008 +0100
-@@ -20,7 +20,9 @@ struct hash {
- int buckets;
- int type;
- uint32_t (*calc_hash)(int, const struct in6_addr *, const struct in6_addr *);
-- int (*match)(struct hash_entry *, const struct in6_addr *, const struct in6_addr *);
-+ int (*match)(struct hash_entry *, const struct in6_addr *,
-+ const struct in6_addr *, uint16_t);
-+
- struct hash_entry **hash_buckets;
- };
-
-@@ -37,19 +39,24 @@ int hash_init(struct hash *h, int type,
- */
- void hash_cleanup(struct hash *h);
- /*
-- * Get data stored in a hash entry based on one or two addresses, depending on type of hash
-+ * Get data stored in a hash entry based on one or two addresses and the bid,
-+ * depending on type of hash. bid=0 means we do not use bid as a search key.
- */
- void *hash_get(const struct hash *h,
- const struct in6_addr *our_addr,
-- const struct in6_addr *peer_addr) ;
-+ const struct in6_addr *peer_addr,
-+ uint16_t bid);
-
- /* Iterate through the hash and call func for every entry */
-
- int hash_iterate(const struct hash *h, int (*func)(void *data, void *arg), void *arg);
-+int hash_iterate_in(const struct hash *h, const struct in6_addr *peer_addr,
-+ int (*func)(void *, void *), void *arg);
-
- /* Add a hash entry to hash */
- int hash_add(const struct hash *h, void *data,
-- struct in6_addr *our_addr, struct in6_addr *peer_addr);
-+ struct in6_addr *our_addr, struct in6_addr *peer_addr,
-+ uint16_t *bid);
-
- /*
- *Delete entry from hash
-@@ -57,6 +64,7 @@ int hash_add(const struct hash *h, void
-
- void hash_delete(const struct hash *h,
- const struct in6_addr *our_addr,
-- const struct in6_addr *peer_addr);
-+ const struct in6_addr *peer_addr,
-+ uint16_t bid);
-
- #endif /* _HASH_H */
-diff -r 82fcd4bea972 src/mh.c
---- a/src/mh.c Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/mh.c Fri Jan 11 17:02:25 2008 +0100
-@@ -77,6 +77,7 @@ int mh_opts_dup_ok[] = {
- 0, /* Nonce Index */
- 0, /* Binding Auth Data */
- 1, /* Mobile Network Prefix */
-+ 1 /* Binding Unique Identifier */
- };
-
- #define __MH_SENTINEL (IP6_MH_TYPE_MAX + 1)
-@@ -443,6 +444,41 @@ int mh_create_opt_mob_net_prefix(struct
- return 0;
- }
-
-+/* MCoA
-+ * mh_create_opt_bid - Create a Binding Unique Identifier Option
-+ * MCoA TODO1: need to be adapted for BULK registration
-+ */
-+int mh_create_opt_bid(struct iovec *iov, uint16_t bid,
-+ uint8_t priority, uint8_t bid_flags)
-+{
-+ int optlen = sizeof(struct ip6_mh_opt_bid);
-+ struct ip6_mh_opt_bid *opt_bid;
-+ uint8_t *data;
-+
-+ iov->iov_base = malloc(optlen);
-+ iov->iov_len = optlen;
-+
-+ if (iov->iov_base == NULL)
-+ return -ENOMEM;
-+
-+ memset(iov->iov_base, 0, iov->iov_len);
-+ data = (uint8_t *)iov->iov_base;
-+
-+ opt_bid = (struct ip6_mh_opt_bid *)data;
-+
-+ opt_bid->ip6mobid_type = IP6_MHOPT_BID;
-+ opt_bid->ip6mobid_len = 4;
-+ opt_bid->ip6mobid_bid = htons(bid);
-+ opt_bid->ip6mobid_priority = priority;
-+ opt_bid->ip6mobid_reserved |= bid_flags;
-+
-+ data += sizeof(struct ip6_mh_opt_bid);
-+ MDBG("BUI sub-option created with BID = %d and priority %d\n",
-+ bid, priority);
-+
-+ return 0;
-+}
-+
- static size_t mh_length(struct iovec *vec, int count)
- {
- size_t len = 0;
-@@ -487,6 +523,9 @@ static int mh_try_pad(const struct iovec
- case IP6_MHOPT_MOB_NET_PRFX:
- pad = optpad(8, 4, len); /* 8n+4 */
- break;
-+ case IP6_MHOPT_BID:
-+ pad = optpad(2, 0, len); /* 2n */
-+ break;
- }
- if (pad > 0) {
- create_opt_pad(&out[n++], pad);
-@@ -497,9 +536,10 @@ static int mh_try_pad(const struct iovec
- out[n].iov_base = in[m].iov_base;
- n++;
- }
-- if (count == 1) {
-+ if (count == 1 || len%8 != 0) {
- pad = optpad(8, 0, len);
- create_opt_pad(&out[n++], pad);
-+ MDBG("Added %d bytes for padding\n", pad);
- }
-
- return n;
-@@ -984,11 +1024,14 @@ void mh_send_brr(struct in6_addr *mn_add
-
- void mh_send_ba(const struct in6_addr_bundle *addrs, uint8_t status,
- uint8_t flags, uint16_t sequence,
-- const struct timespec *lifetime, const uint8_t *key, int iif)
-+ const struct timespec *lifetime,
-+ const uint16_t bid,
-+ const uint8_t priority,
-+ const uint8_t *key, int iif)
- {
- int iovlen = 1;
- struct ip6_mh_binding_ack *ba;
-- struct iovec mh_vec[2];
-+ struct iovec mh_vec[3];
-
- MDBG("status %d\n", status);
-
-@@ -1012,6 +1055,9 @@ void mh_send_ba(const struct in6_addr_bu
- }
- if (key)
- mh_create_opt_auth_data(&mh_vec[iovlen++]);
-+ /* MCoA: Create Binding Unique Identifier Option if needed */
-+ if (bid)
-+ mh_create_opt_bid(&mh_vec[iovlen++], bid, priority, 0);
- mh_send(addrs, mh_vec, iovlen, key, iif);
- free_iov_data(mh_vec, iovlen);
- }
-@@ -1058,8 +1104,11 @@ int mh_bu_parse(struct ip6_mh_binding_up
- return -1;
- if (!IN6_ARE_ADDR_EQUAL(out_addrs->bind_coa, peer_addr)) {
- /* check that there is no circular reference */
-- if (bce_exists(our_addr, out_addrs->bind_coa))
-+ if (bce_exists(our_addr, out_addrs->bind_coa,
-+ MCOA_NO_BID)) {
-+ MDBG("Circular reference found in BC\n");
- return -1;
-+ }
- tssetsec(*lifetime, ntohs(bu->ip6mhbu_lifetime) << 2);
- }
- }
-diff -r 82fcd4bea972 src/mh.h
---- a/src/mh.h Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/mh.h Fri Jan 11 17:02:25 2008 +0100
-@@ -10,7 +10,7 @@
-
- /* If new types or options appear, these should be updated. */
- #define IP6_MH_TYPE_MAX IP6_MH_TYPE_BERROR
--#define IP6_MHOPT_MAX IP6_MHOPT_MOB_NET_PRFX
-+#define IP6_MHOPT_MAX IP6_MHOPT_BID
-
- struct in6_addr_bundle {
- struct in6_addr *src;
-@@ -43,14 +43,20 @@ void mh_send_ba(const struct in6_addr_bu
- void mh_send_ba(const struct in6_addr_bundle *addrs, uint8_t status,
- uint8_t flags, uint16_t sequence,
- const struct timespec *lifetime,
-+ const uint16_t bid,
-+ const uint8_t priority,
- const uint8_t *key, int iif);
-
- static inline void mh_send_ba_err(const struct in6_addr_bundle *addrs,
- uint8_t status, uint8_t flags,
-- uint16_t seqno, const uint8_t *key, int iif)
-+ uint16_t seqno,
-+ const uint16_t bid,
-+ const uint8_t priority,
-+ const uint8_t *key, int iif)
- {
- struct timespec zero = { 0, 0 };
-- mh_send_ba(addrs, status, flags, seqno, &zero, key, iif);
-+ mh_send_ba(addrs, status, flags, seqno, &zero,
-+ bid, priority, key, iif);
- }
-
- void mh_send_be(struct in6_addr *dst,
-@@ -78,6 +84,9 @@ struct list_head;
-
- int mh_create_opt_mob_net_prefix(struct iovec *iov, int mnp_count,
- struct list_head *mnps);
-+
-+int mh_create_opt_bid(struct iovec *iov, uint16_t bid, uint8_t priority,
-+ uint8_t bid_flags);
-
- static inline void *mh_opt(const struct ip6_mh *mh,
- const struct mh_options *mh_opts, uint8_t type)
-diff -r 82fcd4bea972 src/mipv6.h
---- a/src/mipv6.h Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/mipv6.h Fri Jan 11 17:02:25 2008 +0100
-@@ -23,6 +23,7 @@
- /* Constants below have no explicit names in the spec. */
-
- #define MAX_BINDING_LIFETIME (0xffff << 2) /* seconds */
-+#define MCOA_NO_BID 0 /* BID is null */
-
- /* Maximum time for a binding to be unused for CN to still send a BRR
- * before the binding expires */
-diff -r 82fcd4bea972 src/mn.c
---- a/src/mn.c Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/mn.c Fri Jan 11 17:02:25 2008 +0100
-@@ -35,6 +35,8 @@
- #include
- #include
- #include
-+#include
-+#include
-
- #include
- #include
-@@ -94,10 +96,44 @@ const struct timespec min_valid_bu_lifet
- const struct timespec min_valid_bu_lifetime_ts =
- { MIN_VALID_BU_LIFETIME, 0 };
-
-+struct flag_hoa_args {
-+ struct home_addr_info *target;
-+ struct bulentry *bule;
-+ int flag;
-+};
-+
- static int pending_bas = 0;
-
- static void mn_send_home_bu(struct home_addr_info *hai);
- static int mn_ext_tunnel_ops(int request, int old_if, int new_if, void *data);
-+static int flag_hoa(struct ifaddrmsg *ifa, struct rtattr *rta_tb[], void *arg);
-+static int mcoa_iface_rules_add(int iif, struct home_addr_info *hai);
-+static struct bulentry* mcoa_iface_rules_del(int iif,
-+ struct home_addr_info *hai,
-+ int replace);
-+static void mcoa_mn_rules_del(struct home_addr_info *hinfo);
-+static int nemo_mr_rules_add(struct home_addr_info *hinfo);
-+static void nemo_mr_rules_del(struct home_addr_info *hinfo);
-+
-+static int mcoa_mn_init_rt_table(struct bulentry *bule)
-+{
-+ /* MCoA TODO2
-+ * At the moment, the routing table number
-+ * is the BID number. BID must be between
-+ * BCE_TABLE_MIN and BCE_TABLE_MAX
-+ */
-+ assert(bule);
-+
-+ /* If BID is not assigned, default table is taken */
-+ if (!bule->bid)
-+ return (bule->table = RT6_TABLE_MIP6);
-+
-+ if (bule->bid >= BULE_TABLE_MIN && bule->bid <= BULE_TABLE_MAX)
-+ return (bule->table = bule->bid);
-+
-+ MDBG("Routing Table index is out of range");
-+ return -1;
-+}
-
- static int mn_block_rule_del(struct home_addr_info *hai)
- {
-@@ -108,9 +144,9 @@ static int mn_block_rule_del(struct home
- return ret;
- }
-
-- if ((ret = rule_del(NULL, 0, IP6_RULE_PRIO_MIP6_BLOCK, RTN_BLACKHOLE,
-- &hai->hoa.addr, 128, &in6addr_any, 0,
-- FIB_RULE_FIND_SADDR)) < 0)
-+ if ((ret = rule_del(NULL, 0, IP6_RULE_PRIO_MIP6_BLOCK, 0,
-+ RTN_BLACKHOLE, &hai->hoa.addr, 128, &in6addr_any,
-+ 0, FIB_RULE_FIND_SADDR)) < 0)
- MDBG("failed to delete blackhole rule.\n");
- else
- hai->home_block &= ~HOME_ADDR_RULE_BLOCK;
-@@ -126,9 +162,9 @@ static int mn_block_rule_add(struct home
- MDBG("blackhole is already set.\n");
- return ret;
- }
-- if ((ret = rule_add(NULL, 0, IP6_RULE_PRIO_MIP6_BLOCK, RTN_BLACKHOLE,
-- &hai->hoa.addr, 128, &in6addr_any, 0,
-- FIB_RULE_FIND_SADDR)) < 0)
-+ if ((ret = rule_add(NULL, 0, IP6_RULE_PRIO_MIP6_BLOCK,
-+ 0, RTN_BLACKHOLE, &hai->hoa.addr, 128,
-+ &in6addr_any, 0, FIB_RULE_FIND_SADDR)) < 0)
- MDBG("failed to add blackhole rule.\n");
- else
- hai->home_block |= HOME_ADDR_RULE_BLOCK;
-@@ -156,7 +192,10 @@ static void bule_invalidate(struct bulen
- struct home_addr_info *hai = e->home;
- struct in6_addr hoa, peer_addr;
- int type = e->type;
-+ int rules = e->rules;
-+ int if_coa = e->if_coa;
- uint16_t flags = e->flags;
-+ uint16_t bid = e->bid;
-
- if (type != BUL_ENTRY)
- return;
-@@ -173,7 +212,7 @@ static void bule_invalidate(struct bulen
- if (hai->at_home)
- return;
-
-- e = create_bule(&hoa, &peer_addr);
-+ e = create_bule(&hoa, &peer_addr, hai->reg_mcoa?bid:0);
-
- if (e == NULL)
- return;
-@@ -185,6 +224,19 @@ static void bule_invalidate(struct bulen
- e->lifetime = NON_MIP_CN_LTIME_TS;
- e->delay = NON_MIP_CN_LTIME_TS;
- e->callback = bul_expire;
-+ e->priority = get_prio_from_bid(e->bid);
-+ e->mcoa_dereg = 0;
-+ /* MCoA: No tunnels are linked to this BULE anymore */
-+ e->if_tunnel = 0;
-+ /* MCoA: We prevent MIPL to install rules for this entry */
-+ e->rules = 1;
-+ mcoa_mn_init_rt_table(e);
-+
-+ /* MCoA: Erase rules corresponding to this BULE */
-+ /* TODO2: this should be done when bul is deleted */
-+ if(hai->reg_mcoa && rules)
-+ mcoa_iface_rules_del(if_coa, hai, 1);
-+
- if (bul_add(e) < 0)
- bul_delete(e);
- }
-@@ -279,7 +331,10 @@ static void mn_recv_param_prob(const str
- pthread_rwlock_wrlock(&mn_lock);
- if (mn_rr_error_check(laddr, raddr, &addr))
- laddr = &addr;
-- e = bul_get(NULL, laddr, raddr);
-+ /* MCoA TODO1
-+ * All bule with same laddr, raddr should be invalidated
-+ */
-+ e = bul_get(NULL, laddr, raddr, get_bid_from_ifindex(iif));
- if (e != NULL) {
- if (e->flags & IP6_MH_BU_HOME) {
- if (!conf.UseMnHaIPsec &&
-@@ -328,6 +383,19 @@ static int mn_send_bu_msg(struct bulentr
- }
- if (bule->flags & IP6_MH_BU_HOME) {
- struct home_addr_info *hai = bule->home;
-+ /* MCoA TODO1: to update according to latest draft
-+ * Binding Unique Identifier Option
-+ * For deregistration, BUI option is sent only
-+ * when some specific entry needs to be deleted.
-+ * If all entries are deleted, no need to send BUI
-+ */
-+ if ((bu->ip6mhbu_lifetime || !bule->mcoa_dereg)
-+ && hai->reg_mcoa && bule->bid
-+ && mh_create_opt_bid(&iov[iov_ind++], bule->bid,
-+ bule->priority, 0) < 0) {
-+ free_iov_data(iov, iov_ind);
-+ return -ENOMEM;
-+ }
- if (bule->flags & IP6_MH_BU_MR && bu->ip6mhbu_lifetime &&
- bule->home->mnp_count > 0 && conf.MobRtrUseExplicitMode &&
- mh_create_opt_mob_net_prefix(&iov[iov_ind++],
-@@ -353,7 +421,29 @@ static int mn_send_bu_msg(struct bulentr
- addrs.remote_coa = NULL;
- addrs.bind_coa = &bule->coa;
-
-+ /* MCoA
-+ * before sending BU, if !bule->rules then
-+ * add rule from HoA to HA in table bule->table
-+ * This to be able to send a BU if no rules are in
-+ * the RPDB (eg. because of the Reliability option)
-+ */
-+ if(bule->home->reg_mcoa && !bule->rules)
-+ /* MCoA: Rule for HoA to HA from the MN */
-+ rule_add(NULL, bule->table,
-+ IP6_RULE_PRIO_MIP6_HOA_OUT_MCOA, 0, RTN_UNICAST,
-+ &bule->home->hoa.addr, 128, &bule->peer_addr, 128,
-+ FIB_RULE_FIND_SADDR);
-+
- ret = mh_send(&addrs, iov, iov_ind, bind_key, bule->if_coa);
-+
-+ /* MCoA
-+ * Delete the previously installed rule
-+ */
-+ if(bule->home->reg_mcoa && !bule->rules)
-+ rule_del(NULL, bule->table,
-+ IP6_RULE_PRIO_MIP6_HOA_OUT_MCOA, 0, RTN_UNICAST,
-+ &bule->home->hoa.addr, 128, &bule->peer_addr, 128,
-+ FIB_RULE_FIND_SADDR);
-
- if (ret <= 0)
- MDBG("mh_send failed ret: %d\n", ret);
-@@ -363,15 +453,35 @@ static int mn_send_bu_msg(struct bulentr
- return ret;
- }
-
-+struct mn_addr *mcoa_get_current_coa(struct home_addr_info *hai, int iif)
-+{
-+ struct list_head *l;
-+
-+ if(!hai->reg_mcoa)
-+ return hai->current_coa;
-+
-+ list_for_each(l, &hai->mcoa) {
-+ struct mn_addr *coa_entry;
-+ coa_entry = list_entry(l, struct mn_addr, list);
-+ if (coa_entry->iif == iif)
-+ return coa_entry;
-+ }
-+
-+ return NULL;
-+}
-+
- static int mn_get_home_lifetime(struct home_addr_info *hai,
-- struct timespec *lifetime, int dereg)
-+ struct timespec *lifetime,
-+ int iif, int dereg)
- {
- if (!hai->at_home && !dereg) {
-- struct mn_addr *coa = &hai->primary_coa;
-+ /* MCoA: Pick up the CoA from the correct iface */
-+ struct mn_addr *coa = mcoa_get_current_coa(hai, iif);
- struct timespec now;
- unsigned long coa_lft;
- unsigned long hoa_lft;
-
-+ assert(coa);
- clock_gettime(CLOCK_REALTIME, &now);
-
- coa_lft = mpd_curr_lft(&now, &coa->timestamp,
-@@ -403,16 +513,20 @@ static int mn_get_ro_lifetime(struct hom
- if (!hai->at_home && !dereg) {
- struct bulentry *e;
-
-- e = bul_get(hai, NULL, &hai->ha_addr);
-+ e = bul_get(hai, NULL, &hai->ha_addr,
-+ hai->reg_mcoa?
-+ get_bid_from_ifindex(hai->current_coa->iif)
-+ :MCOA_NO_BID);
-
- if (e == NULL || !(e->flags & IP6_MH_BU_HOME)) {
- MDBG("No valid home registration");
- } else {
- struct timespec now;
-- struct mn_addr *coa = &hai->primary_coa;
-+ struct mn_addr *coa = hai->current_coa;
- unsigned long coa_lft;
- unsigned long home_lft;
-
-+ assert(coa);
- clock_gettime(CLOCK_REALTIME, &now);
-
- coa_lft = mpd_curr_lft(&now, &coa->timestamp,
-@@ -432,6 +546,21 @@ static int mn_get_ro_lifetime(struct hom
- return 1;
- }
-
-+/* MCoA
-+ * Deregister a specific bule
-+ */
-+static int mn_dereg_bule(struct bulentry *bule)
-+{
-+ if (bule->type != NON_MIP_CN_ENTRY) {
-+ bule->seq++;
-+ bule->mcoa_dereg = 0;
-+ tsclear(bule->lifetime);
-+ mn_send_bu_msg(bule);
-+ }
-+ bul_delete(bule);
-+ return 0;
-+}
-+
- static int mn_dereg(void *vbule, void *arg)
- {
- struct bulentry *bule = vbule;
-@@ -445,7 +574,20 @@ static int mn_dereg(void *vbule, void *a
- }
- bule->seq++;
- tsclear(bule->lifetime);
-- mn_send_bu_msg(bule);
-+ /* MCoA
-+ * When a MN wants to deregister Multiple CoA,
-+ * one BU is enough to deregister all the CoA
-+ */
-+ if(bule->home->reg_mcoa && bule->mcoa_dereg) {
-+ mn_send_bu_msg(bule);
-+ /* MCoA
-+ * Flag the other entries that match the
-+ * peer address (to avoid sending multiple
-+ * BUs)
-+ */
-+ mcoa_bule_dereg(bule, 0);
-+ } else if (!bule->home->reg_mcoa)
-+ mn_send_bu_msg(bule);
- }
- bul_delete(bule);
- return 0;
-@@ -486,8 +628,9 @@ static int bu_lft_check(struct bulentry
- int dereg;
-
- if (bule->flags & IP6_MH_BU_HOME)
-- dereg = mn_get_home_lifetime(bule->home, &bule->lifetime, 0);
-- else
-+ dereg = mn_get_home_lifetime(bule->home, &bule->lifetime,
-+ bule->if_coa, 0);
-+ else
- dereg = mn_get_ro_lifetime(bule->home, &bule->lifetime,
- bule->dereg);
-
-@@ -544,6 +687,7 @@ static void bu_refresh(struct tq_elem *t
- if (!task_interrupted()) {
- struct bulentry *bule = tq_data(tqe, struct bulentry, tqe);
- int expired;
-+ int iif = bule->if_coa;
- MDBG("Bul refresh type: %d\n", bule->type);
-
- clock_gettime(CLOCK_REALTIME, &bule->lastsent);
-@@ -554,6 +698,10 @@ static void bu_refresh(struct tq_elem *t
-
- bule->seq++;
- bule->callback = bu_resend;
-+ /* MCoA : Check for interface reliability */
-+ if(bule->home->reg_mcoa
-+ && get_reliable_from_ifindex(iif) == 0)
-+ mcoa_iface_rules_del(iif, bule->home, 1);
- pre_bu_bul_update(bule);
- mn_send_bu_msg(bule);
-
-@@ -626,14 +774,53 @@ static int mv_hoa(struct ifaddrmsg *ifa,
- return 0;
- }
-
--int nemo_mr_tnl_routes_add(struct home_addr_info *hai, int ifindex)
-+/*
-+ * Copy home address between two interfaces
-+ */
-+static int cp_hoa(struct ifaddrmsg *ifa, struct rtattr *rta_tb[], void *arg)
-+{
-+ struct mv_hoa_args *mha = arg;
-+ struct home_addr_info *hai = mha->target;
-+ struct mn_addr *hoa = &hai->hoa;
-+ int err;
-+ struct timespec now;
-+ uint32_t preferred = PREFIX_LIFETIME_INFINITE;
-+ uint32_t valid = PREFIX_LIFETIME_INFINITE;
-+ int plen = (mha->if_next == hai->if_tunnel ? 128 : hai->plen);
-+
-+ clock_gettime(CLOCK_REALTIME, &now);
-+
-+ if (hai->lladdr_comp && rta_tb[IFA_CACHEINFO] != NULL) {
-+ struct ifa_cacheinfo *ci = RTA_DATA(rta_tb[IFA_CACHEINFO]);
-+ mn_update_hoa_lifetime(hoa, &now,
-+ ci->ifa_valid, ci->ifa_prefered);
-+ valid = ci->ifa_valid;
-+ preferred = ci->ifa_prefered;
-+ }
-+ if (mha->if_next == ifa->ifa_index)
-+ return 0;
-+
-+ MDBG("Copy HoA %x:%x:%x:%x:%x:%x:%x:%x/%d from iface %d to %d\n",
-+ NIP6ADDR(&hoa->addr), plen, ifa->ifa_index, mha->if_next);
-+
-+ err = addr_add(&hoa->addr, plen,
-+ ifa->ifa_flags|IFA_F_HOMEADDRESS,
-+ ifa->ifa_scope, mha->if_next, preferred, valid);
-+ if (err < 0)
-+ return err;
-+
-+ return 0;
-+}
-+
-+int nemo_mr_tnl_routes_add(struct home_addr_info *hai,
-+ int ifindex, int rtable)
- {
- struct list_head *l;
- struct prefix_list_entry *pe;
- list_for_each(l, &hai->mob_net_prefixes) {
- struct prefix_list_entry *p;
- p = list_entry(l, struct prefix_list_entry, list);
-- if (route_add(ifindex, RT6_TABLE_MIP6, RTPROT_MIP,
-+ if (route_add(ifindex, rtable, RTPROT_MIP,
- 0, IP6_RT_PRIO_MIP6_FWD,
- &p->ple_prefix, p->ple_plen,
- &in6addr_any, 0, NULL) < 0) {
-@@ -646,7 +833,7 @@ undo:
- list_for_each(l, &hai->mob_net_prefixes) {
- struct prefix_list_entry *p;
- p = list_entry(l, struct prefix_list_entry, list);
-- route_del(ifindex, RT6_TABLE_MIP6, IP6_RT_PRIO_MIP6_FWD,
-+ route_del(ifindex, rtable, IP6_RT_PRIO_MIP6_FWD,
- &p->ple_prefix, p->ple_plen, &in6addr_any, 0, NULL);
- if (p == pe)
- break;
-@@ -654,44 +841,47 @@ undo:
- return -1;
- }
-
--static int mn_tnl_state_add(struct home_addr_info *hai, int ifindex, int all)
-+static int mn_tnl_state_add(struct home_addr_info *hai,
-+ int ifindex, int all, int rtable)
- {
- int err = 0;
- if (hai->home_reg_status != HOME_REG_NONE) {
- if ((err = mn_ro_pol_add(hai, ifindex, all)) < 0)
- return err;
-- if ((err = route_add(ifindex, RT6_TABLE_MIP6, RTPROT_MIP, 0,
-+ if ((err = route_add(ifindex, rtable, RTPROT_MIP, 0,
- IP6_RT_PRIO_MIP6_OUT, &in6addr_any, 0,
- &in6addr_any, 0, NULL)) < 0) {
- mn_ro_pol_del(hai, ifindex, all);
- }
- }
- if (hai->mob_rtr &&
-- (err = nemo_mr_tnl_routes_add(hai, ifindex)) < 0) {
-- route_del(ifindex, RT6_TABLE_MIP6, IP6_RT_PRIO_MIP6_OUT,
-+ (err = nemo_mr_tnl_routes_add(hai, ifindex, rtable)) < 0) {
-+ route_del(ifindex, rtable, IP6_RT_PRIO_MIP6_OUT,
- &hai->hoa.addr, 128, &in6addr_any, 0, NULL);
- mn_ro_pol_del(hai, ifindex, all);
- }
- return err;
- }
-
--static void nemo_mr_tnl_routes_del(struct home_addr_info *hai, int ifindex)
-+static void nemo_mr_tnl_routes_del(struct home_addr_info *hai,
-+ int ifindex, int rtable)
- {
- struct list_head *l;
- list_for_each(l, &hai->mob_net_prefixes) {
- struct prefix_list_entry *p;
- p = list_entry(l, struct prefix_list_entry, list);
-- route_del(ifindex, RT6_TABLE_MIP6, IP6_RT_PRIO_MIP6_FWD,
-+ route_del(ifindex, rtable, IP6_RT_PRIO_MIP6_FWD,
- &p->ple_prefix, p->ple_plen, &in6addr_any, 0, NULL);
- }
- }
-
--static void mn_tnl_state_del(struct home_addr_info *hai, int ifindex, int all)
-+static void mn_tnl_state_del(struct home_addr_info *hai, int ifindex,
-+ int all, int rtable)
- {
- if (hai->home_reg_status != HOME_REG_NONE) {
- if (hai->mob_rtr)
-- nemo_mr_tnl_routes_del(hai, ifindex);
-- route_del(ifindex, RT6_TABLE_MIP6, IP6_RT_PRIO_MIP6_OUT,
-+ nemo_mr_tnl_routes_del(hai, ifindex, rtable);
-+ route_del(ifindex, rtable, IP6_RT_PRIO_MIP6_OUT,
- &hai->hoa.addr, 128, &in6addr_any, 0, NULL);
- mn_ro_pol_del(hai, ifindex, all);
- }
-@@ -715,8 +905,18 @@ static void mn_pol_ext_cleanup(struct bu
- static void mn_pol_ext_cleanup(struct bulentry *bule)
- {
- MDBG("\n");
-- mpd_cancel_mps(&bule->hoa, &bule->peer_addr);
-- mn_tnl_state_del(bule->home, bule->home->if_tunnel, 0);
-+ /* MCoA
-+ * MPS is canceled only if the BULE is the last entry
-+ * for the HoA, or when at home
-+ */
-+ if (mcoa_bule_count(bule) == 0 || bule->home->at_home)
-+ mpd_cancel_mps(&bule->hoa, &bule->peer_addr);
-+ if (bule->home->reg_mcoa)
-+ mn_tnl_state_del(bule->home, bule->if_tunnel, 0,
-+ bule->table);
-+ else
-+ mn_tnl_state_del(bule->home, bule->home->if_tunnel,
-+ 0, bule->table);
-
- if (conf.UseMnHaIPsec) {
- mn_ipsec_tnl_update(&bule->peer_addr, &bule->hoa, bule);
-@@ -730,12 +930,13 @@ static int process_first_home_bu(struct
- struct timespec *lifetime)
- {
- int err = 0;
-+ assert(hai->current_coa);
- bule->type = BUL_ENTRY;
- bule->flags = (IP6_MH_BU_HOME | IP6_MH_BU_ACK |
- hai->lladdr_comp | hai->mob_rtr);
- bule->coa_changed = -1;
-- bule->coa = hai->primary_coa.addr;
-- bule->if_coa = hai->primary_coa.iif;
-+ bule->coa = hai->current_coa->addr;
-+ bule->if_coa = hai->current_coa->iif;
- bule->lifetime = *lifetime;
- bule->delay = conf.InitialBindackTimeoutFirstReg_ts;
- bule->callback = bu_resend;
-@@ -744,10 +945,47 @@ static int process_first_home_bu(struct
- bule->ext_cleanup = mn_pol_ext_cleanup;
- bule->home = hai;
- bule->consecutive_resends = 0;
-+ bule->priority = get_prio_from_bid(bule->bid);
-
- hai->home_reg_status = HOME_REG_UNCERTAIN;
-
-- if ((err = mn_tnl_state_add(hai, hai->if_tunnel, 0)) < 0)
-+ /* MCoA: MCoA requires one tunnel per CoA. Need to create a new one */
-+ if (bule->if_tunnel == 0
-+ && hai->reg_mcoa
-+ && get_bid_from_ifindex(hai->current_coa->iif)) {
-+ MDBG("Creating new tunnel for iface %d (BID %d)\n",
-+ hai->current_coa->iif,
-+ get_bid_from_ifindex(hai->current_coa->iif));
-+ bule->if_tunnel = tunnel_add(&hai->hoa.addr,
-+ &hai->ha_addr,
-+ hai->current_coa->iif,
-+ NULL, NULL);
-+ if (bule->if_tunnel <= 0) {
-+ MDBG("Failed to create MN-HA tunnel\n");
-+ return -1;
-+ } else {
-+ MDBG("MN-HA tunnel created (iface tnl = %d)\n",
-+ bule->if_tunnel);
-+ struct flag_hoa_args arg;
-+ arg.target = hai;
-+ arg.flag = 1;
-+ arg.bule = bule;
-+ if (addr_do(&hai->hoa.addr, 128,
-+ bule->if_tunnel, &arg,
-+ flag_hoa) < 0) {
-+ MDBG("addr_do failed for tunnel %d\n",
-+ bule->if_tunnel);
-+ return -1;
-+ }
-+ }
-+ } else if (bule->if_tunnel == 0)
-+ /* MCoA
-+ * If MCoA is not used, then initialise the tunnel
-+ * number to the one in hai
-+ */
-+ bule->if_tunnel = hai->if_tunnel;
-+
-+ if ((err = mn_tnl_state_add(hai, bule->if_tunnel, 0, bule->table)) < 0)
- MDBG("Failed to initialize new bule for HA\n");
- else
- MDBG("New bule for HA\n");
-@@ -781,14 +1019,18 @@ static void mn_send_home_bu(struct home_
- movement_t type_movement = MIP6_TYPE_MOVEMENT_UNKNOWN;
-
- TRACE;
-+ assert(hai->current_coa);
-
- if (IN6_IS_ADDR_UNSPECIFIED(&hai->ha_addr)) {
- MDBG("HA not set for home link\n");
- return;
- }
-- mn_get_home_lifetime(hai, &lifetime, 0);
-+ mn_get_home_lifetime(hai, &lifetime, hai->current_coa->iif, 0);
-
-- if ((bule = bul_get(hai, NULL, &hai->ha_addr)) == NULL) {
-+ if ((bule = bul_get(hai, NULL, &hai->ha_addr,
-+ hai->reg_mcoa?
-+ get_bid_from_ifindex(hai->current_coa->iif)
-+ :MCOA_NO_BID)) == NULL) {
- assert(!hai->at_home);
- /* Create new bul entry for HA */
- if (!tsisset(lifetime)) {
-@@ -807,14 +1049,22 @@ static void mn_send_home_bu(struct home_
- mn_change_ha(hai);
- return;
- }
-- bule = create_bule(&hai->hoa.addr, &hai->ha_addr);
-+ bule = create_bule(&hai->hoa.addr, &hai->ha_addr,
-+ hai->reg_mcoa?
-+ get_bid_from_ifindex(hai->current_coa->iif)
-+ :MCOA_NO_BID);
- if (bule == NULL)
- return;
-- if (process_first_home_bu(bule, hai, &lifetime) < 0 ||
-+ if (mcoa_mn_init_rt_table(bule) < 0 ||
-+ process_first_home_bu(bule, hai, &lifetime) < 0 ||
- bul_add(bule) < 0) {
- bul_delete(bule);
- return;
- }
-+ /* MCoA: Check for interface reliability */
-+ if(get_reliable_from_ifindex(bule->if_coa) > 0)
-+ /* MCoA: Add the rules */
-+ mcoa_iface_rules_add(hai->current_coa->iif, hai);
- type_movement = MIP6_TYPE_MOVEMENT_HL2FL;
- MDBG("New bule for HA\n");
- } else if (bule->type == BUL_ENTRY) {
-@@ -829,8 +1079,8 @@ static void mn_send_home_bu(struct home_
- }
- type_movement = MIP6_TYPE_MOVEMENT_HL2FL;
- } else {
-- bule->coa = hai->primary_coa.addr;
-- bule->if_coa = hai->primary_coa.iif;
-+ bule->coa = hai->current_coa->addr;
-+ bule->if_coa = hai->current_coa->iif;
-
- /* Rate limiting home registration binding updates
- is necessary for multihomed MNs */
-@@ -850,6 +1100,10 @@ static void mn_send_home_bu(struct home_
- bule->callback = bu_resend;
- }
- bule->seq++;
-+ /* MCoA: Check for interface reliability */
-+ if(bule->home->reg_mcoa
-+ && get_reliable_from_ifindex(bule->if_coa) == 0)
-+ mcoa_iface_rules_del(bule->if_coa, bule->home, 1);
- pre_bu_bul_update(bule);
- MDBG("Bule for HA exists. Updating it.\n");
- } else {
-@@ -885,10 +1139,13 @@ static void mn_send_home_bu(struct home_
- &bule->hoa, bule);
- }
- }
-+ /* MCoA: Update the current routing table */
-+ hai->table = bule->table;
- /* Before bul_iterate, tunnel modification should be done. */
-- tunnel_mod(hai->if_tunnel, &hai->primary_coa.addr, &hai->ha_addr,
-- hai->primary_coa.iif, mn_ext_tunnel_ops, hai);
--
-+ bule->if_tunnel = tunnel_mod(bule->if_tunnel, &hai->current_coa->addr,
-+ &hai->ha_addr, hai->current_coa->iif,
-+ mn_ext_tunnel_ops, hai);
-+ hai->if_tunnel = bule->if_tunnel;
- bule->last_coa = bule->coa;
- bule->coa_changed = 0;
-
-@@ -1017,14 +1274,87 @@ static int mn_chk_bauth(struct ip6_mh_bi
- return -1;
- }
-
-+static int mn_disable_mcoa(struct bulentry *bule)
-+{
-+/*
-+ struct bulentry *bule_del;
-+ struct home_addr_info *hai;
-+ struct flag_hoa_args arg;
-+ struct list_head *l, *tmp;
-+ struct net_iface *best_iface = NULL;
-+*/
-+
-+ /* MCoA TODO1: At the moment we simply exit */
-+ MDBG("HA does not accept MCoA registration. Check "\
-+ "your HA or change your MR configuration\n");
-+ kill(0, SIGINT);
-+ return 0;
-+
-+/*
-+ assert(bule);
-+ hai = bule->home;
-+ mcoa_mn_rules_del(hai);
-+ while((bule_del = bul_get(hai, NULL,
-+ &bule->peer_addr, MCOA_NO_BID)))
-+ bul_delete(bule_del);
-+
-+ hai->if_tunnel = tunnel_add(&hai->hoa.addr, &hai->ha_addr,
-+ hai->if_home, NULL, NULL);
-+ if (hai->if_tunnel <= 0) {
-+ MDBG("failed to create MN-HA tunnel\n");
-+ goto clean_err;
-+ }
-+
-+ arg.target = hai;
-+ arg.flag = 1;
-+ if (addr_do(&hai->hoa.addr, 128, hai->if_tunnel,
-+ &arg, flag_hoa) < 0)
-+ goto clean_err;
-+
-+ nemo_mr_rules_del(hai);
-+ hai->reg_mcoa = 0;
-+ nemo_mr_rules_add(hai);
-+ if (rule_add(NULL, RT6_TABLE_MIP6, IP6_RULE_PRIO_MIP6_HOA_OUT, 0,
-+ RTN_UNICAST, &hai->hoa.addr,
-+ 128, &in6addr_any, 0, FIB_RULE_FIND_SADDR) < 0)
-+ goto clean_err;
-+
-+ list_for_each(l, &conf.net_ifaces) {
-+ struct net_iface *iface = NULL;
-+ iface = list_entry(l, struct net_iface, list);
-+ if (!best_iface
-+ || iface->mn_if_bidprio > best_iface->mn_if_bidprio)
-+ best_iface = iface;
-+ }
-+ list_for_each_safe(l, tmp, &conf.net_ifaces) {
-+ struct net_iface *iface = NULL;
-+ iface = list_entry(l, struct net_iface, list);
-+ if (iface != best_iface) {
-+ MDBG("Deleting iface %d\n", iface->ifindex);
-+ list_del(l);
-+ }
-+ }
-+ return 1;
-+
-+clean_err:
-+ rule_del(NULL, RT6_TABLE_MIP6,
-+ IP6_RULE_PRIO_MIP6_HOA_OUT, 0, RTN_UNICAST,
-+ &hai->hoa.addr, 128, &in6addr_any, 0, FIB_RULE_FIND_SADDR);
-+ tunnel_del(hai->if_tunnel, NULL, NULL);
-+
-+ return 0;
-+*/
-+}
-+
- static void mn_recv_ba(const struct ip6_mh *mh, ssize_t len,
- const struct in6_addr_bundle *in, int iif)
- {
- struct ip6_mh_binding_ack *ba;
-+ struct ip6_mh_opt_bid *bui;
- struct mh_options mh_opts;
- struct bulentry *bule;
- struct timespec now, ba_lifetime, br_adv;
-- uint16_t seqno;
-+ uint16_t seqno, bid;
-
- TRACE;
-
-@@ -1036,25 +1366,32 @@ static void mn_recv_ba(const struct ip6_
- ba = (struct ip6_mh_binding_ack *)mh;
-
- pthread_rwlock_wrlock(&mn_lock);
-- bule = bul_get(NULL, in->dst, in->src);
-+
-+ /* MCoA: Lookup in BA options for the BUI sub-option and the BID */
-+ bui = mh_opt(&ba->ip6mhba_hdr, &mh_opts, IP6_MHOPT_BID);
-+ bid = bui ? ntohs(bui->ip6mobid_bid) : MCOA_NO_BID;
-+
-+ bule = bul_get(NULL, in->dst, in->src, bid);
- if (!bule || bule->type != BUL_ENTRY) {
- MDBG("Got BA without corresponding BUL entry "
- "from %x:%x:%x:%x:%x:%x:%x:%x "
- "to home address %x:%x:%x:%x:%x:%x:%x:%x "
-- "with coa %x:%x:%x:%x:%x:%x:%x:%x\n",
-+ "with coa %x:%x:%x:%x:%x:%x:%x:%x"
-+ "and bid %d\n",
- NIP6ADDR(in->src),
- NIP6ADDR(in->dst),
- NIP6ADDR(in->local_coa != NULL ?
-- in->local_coa : &in6addr_any));
-+ in->local_coa : &in6addr_any),
-+ bid);
- pthread_rwlock_unlock(&mn_lock);
- return;
- }
- dbg("Got BA from %x:%x:%x:%x:%x:%x:%x:%x "
- "to home address %x:%x:%x:%x:%x:%x:%x:%x "
-- "with coa %x:%x:%x:%x:%x:%x:%x:%x and status %d\n",
-+ "with coa %x:%x:%x:%x:%x:%x:%x:%x, bid %d and status %d\n",
- NIP6ADDR(in->src), NIP6ADDR(in->dst),
- NIP6ADDR(in->local_coa != NULL ? in->local_coa : &in6addr_any),
-- ba->ip6mhba_status);
-+ bid, ba->ip6mhba_status);
- dbg("Dumping corresponding BULE\n");
- dbg_func(bule, dump_bule);
- /* First check authenticator */
-@@ -1076,6 +1413,17 @@ static void mn_recv_ba(const struct ip6_
- return;
- }
- }
-+ /* MCoA: Check if BID matches */
-+ if (bule->bid && !bui) {
-+ /* The BACK did not have any BID suboption whereas
-+ * we sent a BU with a BID option. MCoA is disabled
-+ * on the node.
-+ */
-+ MDBG("Got BA with no BID option, disabling MCoA registration.\n");
-+ mn_disable_mcoa(bule);
-+ pthread_rwlock_unlock(&mn_lock);
-+ return;
-+ }
- bule->do_send_bu = 0;
- bule->consecutive_resends = 0;
- clock_gettime(CLOCK_REALTIME, &now);
-@@ -1086,11 +1434,18 @@ static void mn_recv_ba(const struct ip6_
- bule->seq = seqno + 1;
- if (bule->flags & IP6_MH_BU_HOME)
- mn_get_home_lifetime(bule->home,
-- &bule->lifetime, 0);
-+ &bule->lifetime,
-+ bule->if_coa,
-+ 0);
- else
- mn_get_ro_lifetime(bule->home,
- &bule->lifetime, 0);
- bule->callback = bu_resend;
-+ /* MCoA: Check for interface reliability */
-+ if(bule->home->reg_mcoa
-+ && get_reliable_from_ifindex(bule->if_coa) == 0)
-+ mcoa_iface_rules_del(bule->if_coa,
-+ bule->home, 1);
- pre_bu_bul_update(bule);
- mn_send_bu_msg(bule);
- bule->delay = conf.InitialBindackTimeoutReReg_ts;
-@@ -1137,6 +1492,10 @@ static void mn_recv_ba(const struct ip6_
- tssetsec(ba_lifetime, ntohs(ba->ip6mhba_lifetime) << 2);
- br_adv = ba_lifetime;
- tsadd(bule->lastsent, ba_lifetime, bule->hard_expire);
-+ /* MCoA: Check for interface reliability */
-+ if(bule->home->reg_mcoa
-+ && get_reliable_from_ifindex(bule->if_coa) == 0)
-+ mcoa_iface_rules_add(bule->if_coa, bule->home);
- if (!(bule->flags & IP6_MH_BU_HOME) || !conf.OptimisticHandoff)
- post_ba_bul_update(bule);
- if (bule->flags & IP6_MH_BU_HOME) {
-@@ -1266,11 +1625,6 @@ struct home_addr_info *mn_get_home_addr_
- return NULL;
- }
-
--struct flag_hoa_args {
-- struct home_addr_info *target;
-- int flag;
--};
--
- static int flag_hoa(struct ifaddrmsg *ifa, struct rtattr *rta_tb[], void *arg)
- {
- /*
-@@ -1279,13 +1633,18 @@ static int flag_hoa(struct ifaddrmsg *if
-
- struct flag_hoa_args *fhoa = arg;
- struct home_addr_info *hai = fhoa->target;
-+ struct bulentry *bule = fhoa->bule;
- struct mn_addr *hoa = &hai->hoa;
- struct in6_addr *addr = RTA_DATA(rta_tb[IFA_ADDRESS]);
- struct timespec now;
- uint32_t preferred;
- uint32_t valid;
-- int err;
-- int plen = (ifa->ifa_index == hai->if_tunnel ? 128 : hai->plen);
-+ int err, plen;
-+
-+ if (hai->reg_mcoa && bule != NULL)
-+ plen = (ifa->ifa_index == bule->if_tunnel ? 128 : hai->plen);
-+ else
-+ plen = (ifa->ifa_index == hai->if_tunnel ? 128 : hai->plen);
-
- clock_gettime(CLOCK_REALTIME, &now);
-
-@@ -1321,6 +1680,220 @@ static int flag_hoa(struct ifaddrmsg *if
- return 0;
- }
-
-+static int mcoa_iface_dflt_hoa_rule_del(struct bulentry *bule,
-+ struct bulentry *best_bule,
-+ struct home_addr_info *hai,
-+ int replace)
-+{
-+ /* MCoA: Delete the default HoA rule */
-+ rule_del(NULL, bule->bid, IP6_RULE_PRIO_MIP6_HOA_OUT,
-+ 0, RTN_UNICAST, &hai->hoa.addr, 128,
-+ &in6addr_any, 0, FIB_RULE_FIND_SADDR);
-+
-+ /* MCoA
-+ * Do not replace the default rules
-+ * if there are no other best bule
-+ */
-+ if(best_bule && best_bule != bule && replace) {
-+ if (rule_add(NULL, best_bule->bid,
-+ IP6_RULE_PRIO_MIP6_HOA_OUT, 0, RTN_UNICAST,
-+ &hai->hoa.addr, 128, &in6addr_any, 0,
-+ FIB_RULE_FIND_SADDR) < 0)
-+ return -1;
-+ }
-+ return 0;
-+}
-+
-+static void mcoa_iface_dflt_mnp_rules_del(struct bulentry *bule,
-+ struct bulentry *best_bule,
-+ struct home_addr_info *hai,
-+ struct prefix_list_entry *p,
-+ int replace)
-+{
-+ /* MCoA: Delete the default MNP rule */
-+ rule_del(NULL, bule->bid, IP6_RULE_PRIO_MIP6_FWD_MCOA,
-+ 0, RTN_UNICAST, &p->ple_prefix, p->ple_plen,
-+ &in6addr_any, 0, 0);
-+
-+ /* MCoA
-+ * Do not replace the default rules
-+ * if there are no other best bule
-+ */
-+ if(best_bule && best_bule != bule && replace) {
-+ rule_add(NULL, best_bule->bid,
-+ IP6_RULE_PRIO_MIP6_FWD_MCOA, 0, RTN_UNICAST,
-+ &p->ple_prefix, p->ple_plen, &in6addr_any, 0, 0);
-+ }
-+}
-+
-+static struct bulentry* mcoa_iface_rules_del(int iif,
-+ struct home_addr_info *hai,
-+ int replace)
-+{
-+ uint16_t bid = hai->reg_mcoa?get_bid_from_ifindex(iif):MCOA_NO_BID;
-+ uint8_t prio_tmp = 0;
-+ struct bulentry *bule, *best_bule = NULL;
-+ struct list_head *l;
-+ int delete_dflt_mnp = 0;
-+
-+ bule = bul_get(hai, NULL, &hai->ha_addr, bid);
-+ if (!hai->reg_mcoa || (bule && !bule->rules))
-+ return NULL;
-+
-+ /* MCoA: Delete rule for HoA traffic from the MN */
-+ rule_del(NULL, bid, IP6_RULE_PRIO_MIP6_HOA_OUT_MCOA,
-+ /* fwmark */ bid, RTN_UNICAST,
-+ &hai->hoa.addr, 128, &in6addr_any, 0,
-+ FIB_RULE_FIND_SADDR);
-+
-+ bul_iterate_in(&hai->ha_addr, bul_highest_priority,
-+ &best_bule);
-+ if(bule && best_bule == bule) {
-+ delete_dflt_mnp = 1;
-+ /* MCoA: search for the next best BULE */
-+ prio_tmp = bule->priority;
-+ bule->priority = 0;
-+ bul_iterate_in(&hai->ha_addr,
-+ bul_highest_priority, &best_bule);
-+ bule->priority = prio_tmp;
-+ /* MCoA: delete the default HoA rule */
-+ mcoa_iface_dflt_hoa_rule_del(bule, best_bule, hai, replace);
-+ }
-+
-+ list_for_each(l, &hai->mob_net_prefixes) {
-+ struct prefix_list_entry *p = NULL;
-+ p = list_entry(l, struct prefix_list_entry, list);
-+ /* MCoA: Delete MNP rule */
-+ rule_del(NULL, bid, IP6_RULE_PRIO_MIP6_FWD_FWM,
-+ /*fwmark*/ bid, RTN_UNICAST, &p->ple_prefix,
-+ p->ple_plen, &in6addr_any, 0, 0);
-+ if(delete_dflt_mnp) {
-+ /* MCoA: Delete default MNP rule */
-+ mcoa_iface_dflt_mnp_rules_del(bule, best_bule,
-+ hai, p, replace);
-+ }
-+ }
-+
-+ if (bule) {
-+ bule->rules = 0;
-+ MDBG("MNP and HoA rules deleted for iface %d bid %d\n",
-+ iif, bule->bid);
-+ }
-+
-+ return bule;
-+}
-+
-+static void mcoa_mn_rules_del(struct home_addr_info *hinfo)
-+{
-+ struct list_head *l;
-+
-+ list_for_each(l, &hinfo->mcoa) {
-+ struct mn_addr *iface = NULL;
-+ iface = list_entry(l, struct mn_addr, list);
-+ mcoa_iface_rules_del(iface->iif, hinfo, 0);
-+ }
-+ rule_del(NULL, 0, IP6_RULE_PRIO_MIP6_HOA_OUT,
-+ 0, RTN_UNICAST, &hinfo->hoa.addr, 128,
-+ &in6addr_any, 0, FIB_RULE_FIND_SADDR);
-+ if (hinfo->at_home && hinfo->reg_mcoa) {
-+ list_for_each(l, &hinfo->mob_net_prefixes) {
-+ struct prefix_list_entry *p = NULL;
-+ p = list_entry(l, struct prefix_list_entry,
-+ list);
-+ rule_del(NULL, RT6_TABLE_MIP6,
-+ IP6_RULE_PRIO_MIP6_FWD, 0,
-+ RTN_UNICAST, &p->ple_prefix,
-+ p->ple_plen, &in6addr_any, 0, 0);
-+ }
-+ }
-+}
-+
-+static int mcoa_iface_rules_add(int iif, struct home_addr_info *hai)
-+{
-+ uint16_t bid = hai->reg_mcoa?get_bid_from_ifindex(iif):MCOA_NO_BID;
-+ struct bulentry *bule, *best_bule = NULL;
-+ struct prefix_list_entry *pe = NULL;
-+ struct list_head *l;
-+ uint8_t prio;
-+
-+ bule = bul_get(hai, NULL, &hai->ha_addr, bid);
-+ if (!bid || !hai->reg_mcoa || !bule || (bule && bule->rules))
-+ return 0;
-+
-+ prio = get_prio_from_bid(bid);
-+
-+ /* MCoA: Rule for HoA traffic from the MN */
-+ if (rule_add(NULL, bid, IP6_RULE_PRIO_MIP6_HOA_OUT_MCOA,
-+ /* fwmark */ bid, RTN_UNICAST,
-+ &hai->hoa.addr, 128, &in6addr_any, 0,
-+ FIB_RULE_FIND_SADDR) < 0)
-+ goto undo;
-+
-+ bul_iterate_in(&hai->ha_addr, bul_highest_priority,
-+ &best_bule);
-+
-+ if (!best_bule || prio >= best_bule->priority) {
-+ rule_del(NULL, 0, IP6_RULE_PRIO_MIP6_HOA_OUT,
-+ 0, RTN_UNICAST, &hai->hoa.addr, 128,
-+ &in6addr_any, 0, FIB_RULE_FIND_SADDR);
-+ if (rule_add(NULL, bid, IP6_RULE_PRIO_MIP6_HOA_OUT,
-+ 0, RTN_UNICAST, &hai->hoa.addr, 128,
-+ &in6addr_any, 0, FIB_RULE_FIND_SADDR) < 0)
-+ goto undo;
-+ }
-+
-+ /* MCoA: Rule for forwarded traffic from the NEMO */
-+ list_for_each(l, &hai->mob_net_prefixes) {
-+ struct prefix_list_entry *p = NULL;
-+ p = list_entry(l, struct prefix_list_entry, list);
-+ if (rule_add(NULL, bid, IP6_RULE_PRIO_MIP6_FWD_FWM,
-+ /*fwmark*/ bid, RTN_UNICAST,
-+ &p->ple_prefix, p->ple_plen,
-+ &in6addr_any, 0, 0) < 0) {
-+ pe = p;
-+ goto undo;
-+ }
-+ /* MCoA
-+ * Add default rules if the bule has the highest
-+ * priority
-+ */
-+ if (!best_bule || prio >= best_bule->priority) {
-+ rule_del(NULL, 0, IP6_RULE_PRIO_MIP6_FWD_MCOA,
-+ 0, RTN_UNICAST, &p->ple_prefix, p->ple_plen,
-+ &in6addr_any, 0, 0);
-+ if (rule_add(NULL, bid, IP6_RULE_PRIO_MIP6_FWD_MCOA,
-+ 0, RTN_UNICAST, &p->ple_prefix, p->ple_plen,
-+ &in6addr_any, 0, 0) < 0)
-+ goto undo;
-+ }
-+ }
-+
-+ bule->rules = 1;
-+ MDBG("MNP and HoA Rules added for interface %d.\n", iif);
-+ return 0;
-+
-+undo:
-+ rule_del(NULL, bid, IP6_RULE_PRIO_MIP6_HOA_OUT_MCOA,
-+ /* fwmark */ bid, RTN_UNICAST,
-+ &hai->hoa.addr, 128, &in6addr_any, 0,
-+ FIB_RULE_FIND_SADDR);
-+
-+ rule_del(NULL, bid, IP6_RULE_PRIO_MIP6_HOA_OUT,
-+ 0, RTN_UNICAST, &hai->hoa.addr, 128,
-+ &in6addr_any, 0, FIB_RULE_FIND_SADDR);
-+
-+ list_for_each(l, &hai->mob_net_prefixes) {
-+ struct prefix_list_entry *p = NULL;
-+ p = list_entry(l, struct prefix_list_entry, list);
-+ rule_del(NULL, bid, IP6_RULE_PRIO_MIP6_FWD_FWM,
-+ /*fwmark*/ bid, RTN_UNICAST, &p->ple_prefix,
-+ p->ple_plen, &in6addr_any, 0, 0);
-+ if (p == pe)
-+ break;
-+ }
-+ return -1;
-+}
-+
- static void nemo_mr_rules_del(struct home_addr_info *hinfo)
- {
- struct list_head *l;
-@@ -1328,11 +1901,17 @@ static void nemo_mr_rules_del(struct hom
- list_for_each(l, &hinfo->mob_net_prefixes) {
- struct prefix_list_entry *p = NULL;
- p = list_entry(l, struct prefix_list_entry, list);
-- rule_del(NULL, RT6_TABLE_MIP6,
-- IP6_RULE_PRIO_MIP6_FWD, RTN_UNICAST,
-- &p->ple_prefix, p->ple_plen, &in6addr_any, 0, 0);
-+ if (hinfo->reg_mcoa) {
-+ rule_del(NULL, 0, IP6_RULE_PRIO_MIP6_FWD_MCOA, 0,
-+ RTN_UNICAST, &p->ple_prefix, p->ple_plen,
-+ &in6addr_any, 0, 0);
-+ } else
-+ rule_del(NULL, RT6_TABLE_MIP6,
-+ IP6_RULE_PRIO_MIP6_FWD, 0, RTN_UNICAST,
-+ &p->ple_prefix, p->ple_plen, &in6addr_any,
-+ 0, 0);
- rule_del(NULL, RT6_TABLE_MAIN,
-- IP6_RULE_PRIO_MIP6_MNP_IN, RTN_UNICAST,
-+ IP6_RULE_PRIO_MIP6_MNP_IN, 0, RTN_UNICAST,
- &in6addr_any, 0, &p->ple_prefix, p->ple_plen, 0);
- }
- }
-@@ -1346,19 +1925,21 @@ static int nemo_mr_rules_add(struct home
- struct prefix_list_entry *p = NULL;
- p = list_entry(l, struct prefix_list_entry, list);
- if (rule_add(NULL, RT6_TABLE_MAIN,
-- IP6_RULE_PRIO_MIP6_MNP_IN, RTN_UNICAST,
-+ IP6_RULE_PRIO_MIP6_MNP_IN, 0, RTN_UNICAST,
- &in6addr_any, 0,
- &p->ple_prefix, p->ple_plen, 0) < 0) {
- pe = p;
- goto undo;
- }
-- if (rule_add(NULL, RT6_TABLE_MIP6,
-- IP6_RULE_PRIO_MIP6_FWD, RTN_UNICAST,
-- &p->ple_prefix, p->ple_plen,
-- &in6addr_any, 0, 0) < 0) {
-+ if (!hinfo->reg_mcoa
-+ && rule_add(NULL, RT6_TABLE_MIP6,
-+ IP6_RULE_PRIO_MIP6_FWD, 0, RTN_UNICAST,
-+ &p->ple_prefix, p->ple_plen,
-+ &in6addr_any, 0, 0) < 0) {
- rule_del(NULL, RT6_TABLE_MAIN,
-- IP6_RULE_PRIO_MIP6_MNP_IN, RTN_UNICAST,
-- &in6addr_any, 0, &p->ple_prefix, p->ple_plen, 0);
-+ IP6_RULE_PRIO_MIP6_MNP_IN, 0,
-+ RTN_UNICAST, &in6addr_any, 0,
-+ &p->ple_prefix, p->ple_plen, 0);
- pe = p;
- goto undo;
- }
-@@ -1368,17 +1949,25 @@ undo:
- list_for_each(l, &hinfo->mob_net_prefixes) {
- struct prefix_list_entry *p = NULL;
- p = list_entry(l, struct prefix_list_entry, list);
-- rule_del(NULL, RT6_TABLE_MIP6,
-- IP6_RULE_PRIO_MIP6_FWD, RTN_UNICAST,
-- &p->ple_prefix, p->ple_plen, &in6addr_any, 0, 0);
-+ if (!hinfo->reg_mcoa) {
-+ rule_del(NULL, RT6_TABLE_MIP6,
-+ IP6_RULE_PRIO_MIP6_FWD, 0, RTN_UNICAST,
-+ &p->ple_prefix, p->ple_plen,
-+ &in6addr_any, 0, 0);
-+ }
- rule_del(NULL, RT6_TABLE_MAIN,
-- IP6_RULE_PRIO_MIP6_MNP_IN, RTN_UNICAST,
-+ IP6_RULE_PRIO_MIP6_MNP_IN, 0, RTN_UNICAST,
- &in6addr_any, 0, &p->ple_prefix, p->ple_plen, 0);
- if (p == pe)
- break;
- }
- return -1;
- }
-+
-+struct mcoa_tnl_id {
-+ struct list_head list;
-+ int tnl_id;
-+};
-
- static void clean_home_addr_info(struct home_addr_info *hai)
- {
-@@ -1390,17 +1979,24 @@ static void clean_home_addr_info(struct
- nemo_mr_rules_del(hai);
- arg.target = hai;
- arg.flag = 0;
-- addr_do(&hai->hoa.addr, plen,
-- hai->hoa.iif, &arg, flag_hoa);
-+ /* MCoA: Flag HoA on the tunnel iface is not necessary here */
-+ if (!hai->reg_mcoa)
-+ addr_do(&hai->hoa.addr, plen,
-+ hai->hoa.iif, &arg, flag_hoa);
- bul_iterate(&hai->bul, mn_dereg, NULL);
-- bul_home_cleanup(&hai->bul);
--
-+ /* MCoA: Delete all mn rules */
-+ if (hai->reg_mcoa)
-+ mcoa_mn_rules_del(hai);
- mn_block_rule_del(hai);
-
-- rule_del(NULL, RT6_TABLE_MIP6,
-- IP6_RULE_PRIO_MIP6_HOA_OUT, RTN_UNICAST,
-- &hai->hoa.addr, 128, &in6addr_any, 0, FIB_RULE_FIND_SADDR);
-- tunnel_del(hai->if_tunnel, NULL, NULL);
-+ if (!hai->reg_mcoa) {
-+ rule_del(NULL, RT6_TABLE_MIP6,
-+ IP6_RULE_PRIO_MIP6_HOA_OUT, 0, RTN_UNICAST,
-+ &hai->hoa.addr, 128, &in6addr_any, 0,
-+ FIB_RULE_FIND_SADDR);
-+ tunnel_del(hai->if_tunnel, NULL, NULL);
-+ }
-+ bul_home_cleanup(&hai->bul);
- dhaad_stop(hai);
- free(hai);
- }
-@@ -1448,6 +2044,11 @@ static struct home_addr_info *hai_copy(s
- &hai->mob_net_prefixes) < 0)
- goto mutex_undo;
-
-+ INIT_LIST_HEAD(&hai->mcoa);
-+ if (hai->reg_mcoa &&
-+ prefix_list_copy(&conf_hai->mcoa, &hai->mcoa) < 0)
-+ goto mutex_undo;
-+
- INIT_LIST_HEAD(&hai->ro_policies);
- if (rpl_copy(&conf_hai->ro_policies, &hai->ro_policies) < 0)
- goto mnp_undo;
-@@ -1493,17 +2094,22 @@ static int conf_home_addr_info(struct ho
- MDBG("HA address %x:%x:%x:%x:%x:%x:%x:%x\n",
- NIP6ADDR(&hai->ha_addr));
- }
-- hai->if_tunnel = tunnel_add(&hai->hoa.addr, &hai->ha_addr,
-- hai->if_home, NULL, NULL);
-+ /* MCoA: tunnel is created only if MCoA registration is not used */
-+ if(!hai->reg_mcoa) {
-+ hai->if_tunnel = tunnel_add(&hai->hoa.addr,
-+ &hai->ha_addr,
-+ hai->if_home, NULL, NULL);
-
-- if (hai->if_tunnel <= 0) {
-- MDBG("failed to create MN-HA tunnel\n");
-- goto clean_err;
-- }
-- if (rule_add(NULL, RT6_TABLE_MIP6,
-- IP6_RULE_PRIO_MIP6_HOA_OUT, RTN_UNICAST,
-- &hai->hoa.addr, 128, &in6addr_any, 0, FIB_RULE_FIND_SADDR) < 0) {
-- goto clean_err;
-+ if (hai->if_tunnel <= 0) {
-+ MDBG("failed to create MN-HA tunnel\n");
-+ goto clean_err;
-+ }
-+ if (rule_add(NULL, RT6_TABLE_MIP6,
-+ IP6_RULE_PRIO_MIP6_HOA_OUT, 0, RTN_UNICAST,
-+ &hai->hoa.addr, 128, &in6addr_any, 0,
-+ FIB_RULE_FIND_SADDR) < 0) {
-+ goto clean_err;
-+ }
- }
-
- if (mn_block_rule_add(hai) < 0)
-@@ -1524,16 +2130,25 @@ static int conf_home_addr_info(struct ho
- PREFIX_LIFETIME_INFINITE,
- PREFIX_LIFETIME_INFINITE);
-
-- arg.target = hai;
-- arg.flag = 1;
-+ /* MCoA */
-+ if(!hai->reg_mcoa) {
-+ arg.target = hai;
-+ arg.flag = 1;
-
-- if (addr_do(&hai->hoa.addr, 128,
-- hai->if_tunnel, &arg, flag_hoa) < 0) {
-- goto clean_err;
-+ if (addr_do(&hai->hoa.addr, 128,
-+ hai->if_tunnel, &arg, flag_hoa) < 0) {
-+ goto clean_err;
-+ }
- }
- if (hai->mob_rtr && nemo_mr_rules_add(hai) < 0) {
- goto clean_err;
- }
-+ /* MCoA TODO1
-+ * For Home-CoA support, hai->at_home must be initialized to 0
-+ * if(hai->reg_mcoa) hai->at_home = 0;
-+ * BUT Home-CoA solution seems to be deprecated by the no-NDP
-+ * solution
-+ */
- hai->at_home = hai->hoa.iif == hai->if_home;
- pthread_rwlock_wrlock(&mn_lock);
- list_add(&hai->list, &home_addr_list);
-@@ -1635,7 +2250,11 @@ int mn_update_home_prefix(struct home_ad
- if (!hai->at_home) {
- struct bulentry *e;
-
-- e = bul_get(hai, NULL, &hai->ha_addr);
-+ /* MCoA TODO1
-+ * Do the same for all entries that match &hai->ha_addr
-+ */
-+ e = bul_get(hai, NULL, &hai->ha_addr, MCOA_NO_BID);
-+
- if (e == NULL || !(e->flags & IP6_MH_BU_HOME))
- return -ENOENT;
-
-@@ -1668,8 +2287,9 @@ static int mn_get_ro_coa(const struct in
- return ret;
- hai = mn_get_home_addr(hoa);
- if (hai) {
-- *coa = hai->primary_coa.addr;
-- ret = hai->primary_coa.iif;
-+ assert(hai->current_coa);
-+ *coa = hai->current_coa->addr;
-+ ret = hai->current_coa->iif;
- } else {
- MDBG("Failed to find a home address info\n");
- ret = -1;
-@@ -1683,14 +2303,14 @@ static inline void linklocal_rt_rules_de
- static inline void linklocal_rt_rules_del(void)
- {
- rule_del(NULL, RT6_TABLE_MAIN,
-- IP6_RULE_PRIO_MIP6_COA_OUT, RTN_UNICAST,
-+ IP6_RULE_PRIO_MIP6_COA_OUT, 0, RTN_UNICAST,
- &linklocal_prefix, 64, &in6addr_any, 0, 0);
- }
-
- static inline int linklocal_rt_rules_add(void)
- {
- return rule_add(NULL, RT6_TABLE_MAIN,
-- IP6_RULE_PRIO_MIP6_COA_OUT, RTN_UNICAST,
-+ IP6_RULE_PRIO_MIP6_COA_OUT, 0, RTN_UNICAST,
- &linklocal_prefix, 64, &in6addr_any, 0, 0);
- }
-
-@@ -1705,12 +2325,13 @@ static int mn_ext_tunnel_ops(int request
- mha.if_next = new_if;
- mha.target = hai;
-
-+ /* MCoA: Update state for the correct table (hai->table) */
- if (hai->hoa.iif == old_if &&
-- (mn_tnl_state_add(hai, new_if, 1) ||
-+ (mn_tnl_state_add(hai, new_if, 1, hai->table) ||
- addr_do(&hai->hoa.addr, 128, old_if, &mha, mv_hoa) < 0))
- goto undo;
-
-- mn_tnl_state_del(hai, old_if, 1);
-+ mn_tnl_state_del(hai, old_if, 1, hai->table);
- hai->if_tunnel = new_if;
- return 0;
- undo:
-@@ -1718,28 +2339,52 @@ undo:
-
- if (hai->hoa.iif == new_if)
- addr_do(&hai->hoa.addr, 128, new_if, &mha, mv_hoa);
-- mn_tnl_state_del(hai, new_if, 1);
-+ mn_tnl_state_del(hai, new_if, 1, hai->table);
- return -1;
- }
-
- static int mn_move(struct home_addr_info *hai)
- {
- struct mv_hoa_args mha;
-+ struct list_head *l;
-
- mha.target = hai;
-
- TRACE;
-+ assert(hai->current_coa);
-
- if (hai->at_home) {
- int plen = (hai->hoa.iif == hai->if_tunnel ? 128 : hai->plen);
- struct bulentry *e;
- MDBG("in home net\n");
-+ /* MCoA
-+ * If we are in the home network, add a rule to
-+ * RT6_TABLE_MIP6 to allow routing of the packets from
-+ * the MNNs (routes in RT6_TABLE_MIP6 are
-+ * added/deleted in movement.c/md_update_router_stats,
-+ * __md_free_router) and the MR.
-+ */
-+ if (hai->reg_mcoa) {
-+ list_for_each(l, &hai->mob_net_prefixes) {
-+ struct prefix_list_entry *p = NULL;
-+ p = list_entry(l, struct prefix_list_entry,
-+ list);
-+ rule_add(NULL, RT6_TABLE_MIP6,
-+ IP6_RULE_PRIO_MIP6_FWD, 0,
-+ RTN_UNICAST, &p->ple_prefix,
-+ p->ple_plen, &in6addr_any, 0, 0);
-+ }
-+ }
- if (hai->home_reg_status == HOME_REG_NONE &&
-- (e = bul_get(hai, NULL, &hai->ha_addr)) != NULL &&
-+ (e = bul_get(hai, NULL, &hai->ha_addr,
-+ hai->reg_mcoa?
-+ get_bid_from_ifindex(hai->current_coa->iif)
-+ :MCOA_NO_BID))
-+ != NULL &&
- e->flags & IP6_MH_BU_HOME && e->type != BUL_ENTRY)
- bul_delete(e);
-- if (hai->hoa.iif != hai->primary_coa.iif) {
-- mha.if_next = hai->primary_coa.iif;
-+ if (hai->hoa.iif != hai->current_coa->iif) {
-+ mha.if_next = hai->current_coa->iif;
- addr_do(&hai->hoa.addr, plen,
- hai->hoa.iif, &mha, mv_hoa);
- if (hai->home_reg_status == HOME_REG_NONE) {
-@@ -1760,10 +2405,33 @@ static int mn_move(struct home_addr_info
- hai->pend_ba = 0;
- pending_bas--;
- }
-+ /* MCoA
-+ * When in a foreign network, delete the
-+ * rules to RT6_TABLE_MIP6
-+ */
-+ if (hai->reg_mcoa) {
-+ list_for_each(l, &hai->mob_net_prefixes) {
-+ struct prefix_list_entry *p = NULL;
-+ p = list_entry(l, struct prefix_list_entry,
-+ list);
-+ rule_del(NULL, RT6_TABLE_MIP6,
-+ IP6_RULE_PRIO_MIP6_FWD, 0,
-+ RTN_UNICAST, &p->ple_prefix,
-+ p->ple_plen, &in6addr_any, 0, 0);
-+ }
-+ }
- if (hai->hoa.iif != hai->if_tunnel) {
- mha.if_next = hai->if_tunnel;
-- addr_do(&hai->hoa.addr, hai->plen,
-- hai->hoa.iif, &mha, mv_hoa);
-+ /* MCoA
-+ * HoA is moved if we do not use MCoA,
-+ * HoA is copied if we use MCoA
-+ */
-+ if (hai->reg_mcoa)
-+ addr_do(&hai->hoa.addr, hai->plen,
-+ hai->hoa.iif, &mha, cp_hoa);
-+ else
-+ addr_do(&hai->hoa.addr, hai->plen,
-+ hai->hoa.iif, &mha, mv_hoa);
- }
- do_handoff(hai);
- }
-@@ -1951,6 +2619,7 @@ static int mn_do_dad(struct home_addr_in
- struct in6_addr solicit;
- int type = FLUSH_ALL;
-
-+ assert(hai->current_coa);
- if ((sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0)
- return ret;
-
-@@ -1963,22 +2632,22 @@ static int mn_do_dad(struct home_addr_in
- sizeof(struct icmp6_filter));
-
- ipv6_addr_solict_mult(&hai->hoa.addr, &solicit);
-- if_mc_group(sock, hai->primary_coa.iif, &in6addr_all_nodes_mc,
-+ if_mc_group(sock, hai->current_coa->iif, &in6addr_all_nodes_mc,
- IPV6_JOIN_GROUP);
-- if_mc_group(sock, hai->primary_coa.iif, &solicit, IPV6_JOIN_GROUP);
-+ if_mc_group(sock, hai->current_coa->iif, &solicit, IPV6_JOIN_GROUP);
-
- if (hai->home_reg_status == HOME_REG_NONE) {
- if (hai->lladdr_comp) {
- struct in6_addr lladdr;
- ipv6_addr_llocal(&hai->hoa.addr, &lladdr);
- if (mn_addr_do_dad(sock, NULL, &lladdr, 64,
-- hai->primary_coa.iif, 0) < 0) {
-+ hai->current_coa->iif, 0) < 0) {
- MDBG("Link-local DAD failed!\n");
- goto err;
- }
- }
- if (mn_addr_do_dad(sock, hai, &hai->hoa.addr, hai->plen,
-- hai->primary_coa.iif, 0) < 0) {
-+ hai->current_coa->iif, 0) < 0) {
- MDBG("HoA DAD failed!\n");
- goto err;
- }
-@@ -1986,7 +2655,7 @@ static int mn_do_dad(struct home_addr_in
- mn_send_home_na(hai);
- ret = mn_move(hai);
- } else if (!mn_addr_do_dad(sock, hai, &hai->hoa.addr,
-- hai->plen, hai->primary_coa.iif, 1)) {
-+ hai->plen, hai->current_coa->iif, 1)) {
- ret = mn_move(hai);
- }
- out:
-@@ -2009,15 +2678,19 @@ static inline void mn_update_coa_lifetim
-
- static void mn_coa_updated(struct home_addr_info *hai)
- {
-+ assert(hai->current_coa);
- if (!hai->at_home) {
- struct bulentry *e;
- struct mn_addr *coa;
-
-- e = bul_get(hai, NULL, &hai->ha_addr);
-+ e = bul_get(hai, NULL, &hai->ha_addr,
-+ hai->reg_mcoa?
-+ get_bid_from_ifindex(hai->current_coa->iif)
-+ :MCOA_NO_BID);
- if (e == NULL || !(e->flags & IP6_MH_BU_HOME))
- return;
-
-- coa = &hai->primary_coa;
-+ coa = hai->current_coa;
-
- MDBG2("preferred_time %u valid_life %u\n",
- coa->preferred_time.tv_sec,
-@@ -2075,6 +2748,10 @@ static struct md_inet6_iface *mn_get_ifa
- list_for_each(l, iface_list) {
- struct md_inet6_iface *iface;
- iface = list_entry(l, struct md_inet6_iface, list);
-+ /* MCoA TODO1
-+ * If MCoA is used, MCoA preference must be used instead
-+ * of interfaces preference
-+ */
- if (mn_verify_iface(iface) &&
- (best_iface == NULL ||
- (best_iface)->preference > iface->preference ||
-@@ -2119,6 +2796,106 @@ static struct md_coa *mn_get_coa(const s
- return best_coa;
- }
-
-+static int mcoa_mn_make_ho_verdict(const struct movement_event *me,
-+ const struct home_addr_info *hai,
-+ struct md_router **next_rtr,
-+ struct md_coa **next_coa)
-+{
-+ /* MCoA
-+ * The handoff algorithm is different from
-+ * mn_make_ho_verdict because we do not perform vertical
-+ * handover, but only horizontal handovers.
-+ */
-+ struct md_router *rtr;
-+ struct md_coa *coa = NULL;
-+ int force = 0;
-+
-+ /* MCoA TODO1
-+ * For Home-CoA support, remove this if(){}
-+ * BUT Home-CoA seems to be deprecated
-+ */
-+ if (me->iface != NULL &&
-+ (rtr = md_get_first_router(&me->iface->default_rtr)) != NULL &&
-+ mn_is_at_home(&rtr->prefixes, &hai->home_prefix, hai->home_plen)) {
-+ *next_rtr = rtr;
-+ *next_coa = NULL;
-+ return MN_HO_RETURN_HOME;
-+ }
-+ switch (me->event_type) {
-+ case ME_DHAAD:
-+ force = 1;
-+ break;
-+ case ME_IFACE_DOWN:
-+ case ME_LINK_DOWN:
-+ case ME_RTR_EXPIRED:
-+ break;
-+ case ME_RTR_NEW:
-+ assert(!list_empty(&me->iface->default_rtr));
-+ case ME_LINK_UP:
-+ assert(me->iface != NULL);
-+ break;
-+ case ME_RTR_BACK:
-+ case ME_RTR_UPDATED:
-+ assert(me->iface != NULL);
-+ assert(!list_empty(&me->iface->default_rtr));
-+
-+ *next_coa = md_get_coa(&me->iface->coas,
-+ &hai->current_coa->addr);
-+ if (*next_coa == NULL)
-+ break;
-+ *next_rtr = md_get_first_router(&me->iface->default_rtr);
-+ return MN_HO_REESTABLISH;
-+ case ME_COA_NEW:
-+ assert(me->iface != NULL);
-+ assert(me->coa != NULL);
-+ assert(me->iface->ifindex == me->coa->ifindex);
-+ break;
-+ case ME_COA_EXPIRED:
-+ assert(me->iface != NULL);
-+ assert(me->coa != NULL);
-+ assert(me->iface->ifindex == me->coa->ifindex);
-+
-+ if (IN6_ARE_ADDR_EQUAL(&hai->current_coa->addr,
-+ &me->coa->addr))
-+ break;
-+ return MN_HO_IGNORE;
-+ case ME_COA_LFT_DEC:
-+ case ME_COA_LFT_INC:
-+ assert(me->iface != NULL);
-+ assert(me->coa != NULL);
-+ assert(me->iface->ifindex == me->coa->ifindex);
-+
-+ if (!IN6_ARE_ADDR_EQUAL(&hai->current_coa->addr,
-+ &me->coa->addr)) {
-+ return MN_HO_IGNORE;
-+ }
-+
-+ *next_coa = me->coa;
-+ return MN_HO_CHECK_LIFETIME;
-+ default:
-+ return MN_HO_IGNORE;
-+ }
-+ if (!mn_verify_iface(me->iface))
-+ return MN_HO_INVALIDATE;
-+
-+ coa = mn_get_coa(hai, me->iface->ifindex,
-+ &hai->current_coa->addr, &me->iface->coas);
-+
-+ if (coa == NULL)
-+ return MN_HO_INVALIDATE;
-+
-+ if (!force &&
-+ IN6_ARE_ADDR_EQUAL(&coa->addr, &hai->current_coa->addr))
-+ return MN_HO_IGNORE;
-+
-+ if (list_empty(&me->iface->default_rtr))
-+ return MN_HO_IGNORE;
-+
-+ *next_rtr = md_get_first_router(&me->iface->default_rtr);
-+ *next_coa = coa;
-+ return MN_HO_PROCEED;
-+}
-+
- static int mn_make_ho_verdict(const struct movement_event *me,
- const struct home_addr_info *hai,
- struct md_router **next_rtr,
-@@ -2127,9 +2904,11 @@ static int mn_make_ho_verdict(const stru
- struct md_inet6_iface *old_iface = NULL, *new_iface = NULL;
- struct md_router *rtr;
- struct md_coa *coa = NULL;
-- int pref_iif = hai->primary_coa.iif; /* prefer current CoA interface */
-+ int pref_iif;
- int force = 0;
-
-+ assert(hai->current_coa);
-+ pref_iif = hai->current_coa->iif; /* prefer current CoA interface */
- if (me->iface != NULL &&
- (rtr = md_get_first_router(&me->iface->default_rtr)) != NULL &&
- mn_is_at_home(&rtr->prefixes, &hai->home_prefix, hai->home_plen)) {
-@@ -2170,7 +2949,7 @@ static int mn_make_ho_verdict(const stru
- return MN_HO_IGNORE;
-
- *next_coa = md_get_coa(&old_iface->coas,
-- &hai->primary_coa.addr);
-+ &hai->current_coa->addr);
- if (*next_coa == NULL)
- break;
- *next_rtr = md_get_first_router(&old_iface->default_rtr);
-@@ -2187,7 +2966,7 @@ static int mn_make_ho_verdict(const stru
-
- if (old_iface == NULL ||
- (old_iface == me->iface &&
-- IN6_ARE_ADDR_EQUAL(&hai->primary_coa.addr,
-+ IN6_ARE_ADDR_EQUAL(&hai->current_coa->addr,
- &me->coa->addr)))
- break;
- return MN_HO_IGNORE;
-@@ -2201,7 +2980,7 @@ static int mn_make_ho_verdict(const stru
- break;
-
- if (old_iface != me->iface ||
-- !IN6_ARE_ADDR_EQUAL(&hai->primary_coa.addr,
-+ !IN6_ARE_ADDR_EQUAL(&hai->current_coa->addr,
- &me->coa->addr))
- return MN_HO_IGNORE;
-
-@@ -2216,13 +2995,13 @@ static int mn_make_ho_verdict(const stru
- return MN_HO_INVALIDATE;
-
- coa = mn_get_coa(hai, new_iface->ifindex,
-- &hai->primary_coa.addr, &new_iface->coas);
-+ &hai->current_coa->addr, &new_iface->coas);
-
- if (coa == NULL)
- return MN_HO_INVALIDATE;
-
- if (!force && new_iface == old_iface &&
-- IN6_ARE_ADDR_EQUAL(&coa->addr, &hai->primary_coa.addr))
-+ IN6_ARE_ADDR_EQUAL(&coa->addr, &hai->current_coa->addr))
- return MN_HO_IGNORE;
-
- if (list_empty(&new_iface->default_rtr))
-@@ -2231,6 +3010,100 @@ static int mn_make_ho_verdict(const stru
- *next_rtr = md_get_first_router(&new_iface->default_rtr);
- *next_coa = coa;
- return MN_HO_PROCEED;
-+}
-+
-+static void mcoa_mn_chk_ho_verdict(struct home_addr_info *hai,
-+ const struct movement_event *event)
-+{
-+ struct md_router *rtr = NULL;
-+ struct md_coa *coa = NULL;
-+ struct bulentry *bule;
-+ int move_home = 0;
-+ int active_coa = 0;
-+
-+ if ((bule = bul_get(hai, NULL, &hai->ha_addr,
-+ hai->reg_mcoa?
-+ get_bid_from_ifindex(event->iface->ifindex)
-+ :MCOA_NO_BID)))
-+ active_coa = mcoa_bule_count(bule);
-+
-+ if (event->event_type == ME_COA_EXPIRED &&
-+ IN6_ARE_ADDR_EQUAL(&event->coa->addr, &hai->hoa.addr))
-+ return;
-+
-+ hai->current_coa = mcoa_get_current_coa(hai, event->iface->ifindex);
-+ if (hai->current_coa == NULL)
-+ return;
-+
-+ hai->verdict = mcoa_mn_make_ho_verdict(event, hai, &rtr, &coa);
-+ MDBG2("Verdict %d for iface %d\n",
-+ hai->verdict, hai->current_coa->iif);
-+
-+ if (hai->verdict == MN_HO_IGNORE)
-+ return;
-+
-+ if (hai->verdict == MN_HO_INVALIDATE) {
-+ /* MCoA
-+ * Unless this is the last available interface
-+ * Rules related to this iface are deleted,
-+ * BULE is deleted, and deregistration BU is sent
-+ */
-+ if (active_coa > 1
-+ && (bule = mcoa_iface_rules_del(hai->current_coa->iif,
-+ hai, 1)))
-+ /* MCoA TODO2
-+ * Send a deregistration BU
-+ * Is it the correct place to do that?
-+ * because when BACK is received, BULE has
-+ * already been deleted
-+ * (actually BAck cannot be received at the BULE's CoA
-+ * because the iface is down...)
-+ */
-+ mn_dereg_bule(bule);
-+ hai->current_coa = NULL;
-+ return;
-+ }
-+ if (rtr != NULL)
-+ move_home = mn_home_rtr_chk(hai, rtr);
-+
-+ if (hai->verdict == MN_HO_CHECK_LIFETIME) {
-+ mn_update_coa_lifetime(hai->current_coa, coa);
-+ mn_coa_updated(hai);
-+ } else if (hai->verdict == MN_HO_REESTABLISH) {
-+ mn_update_coa_lifetime(hai->current_coa, coa);
-+ mn_coa_updated(hai);
-+ } else {
-+ switch (hai->verdict) {
-+ case MN_HO_PROCEED:
-+ hai->current_coa->addr = coa->addr;
-+ mn_update_coa_lifetime(hai->current_coa, coa);
-+ /* MCoA
-+ * Rules related to this iface are added if needed
-+ */
-+ mcoa_iface_rules_add(hai->current_coa->iif, hai);
-+ break;
-+ case MN_HO_RETURN_HOME:
-+ hai->current_coa->addr = hai->hoa.addr;
-+ mcoa_iface_rules_del(hai->current_coa->iif, hai, 1);
-+ break;
-+ default:
-+ return;
-+ }
-+ if (hai->at_home && !hai->pend_ba) {
-+ /* check if router is HA */
-+ if (hai->home_reg_status != HOME_REG_NONE &&
-+ rtr_addr_chk(rtr, &hai->ha_addr)) {
-+ mn_move(hai);
-+ } else if (hai->home_reg_status != HOME_REG_NONE ||
-+ move_home) {
-+ int type = FLUSH_FAILED;
-+ mn_do_dad(hai, 0);
-+ if (hai->home_reg_status == HOME_REG_NONE)
-+ bul_iterate(&hai->bul,
-+ _bul_flush, &type);
-+ }
-+ }
-+ }
- }
-
- static void mn_chk_ho_verdict(struct home_addr_info *hai,
-@@ -2244,35 +3117,36 @@ static void mn_chk_ho_verdict(struct hom
- IN6_ARE_ADDR_EQUAL(&event->coa->addr, &hai->hoa.addr))
- return;
-
-+ assert(hai->current_coa);
- hai->verdict = mn_make_ho_verdict(event, hai, &rtr, &coa);
-
- if (hai->verdict == MN_HO_IGNORE)
- return;
-
- if (hai->verdict == MN_HO_INVALIDATE) {
-- hai->primary_coa.iif = 0;
-+ hai->current_coa->iif = 0;
- return;
- }
- if (rtr != NULL)
- move_home = mn_home_rtr_chk(hai, rtr);
-
- if (hai->verdict == MN_HO_CHECK_LIFETIME) {
-- mn_update_coa_lifetime(&hai->primary_coa, coa);
-+ mn_update_coa_lifetime(hai->current_coa, coa);
- mn_coa_updated(hai);
- } else if (hai->verdict == MN_HO_REESTABLISH) {
-- hai->primary_coa.iif = coa->ifindex;
-- mn_update_coa_lifetime(&hai->primary_coa, coa);
-+ hai->current_coa->iif = coa->ifindex;
-+ mn_update_coa_lifetime(hai->current_coa, coa);
- mn_coa_updated(hai);
- } else {
- switch (hai->verdict) {
- case MN_HO_PROCEED:
-- hai->primary_coa.iif = coa->ifindex;
-- hai->primary_coa.addr = coa->addr;
-- mn_update_coa_lifetime(&hai->primary_coa, coa);
-+ hai->current_coa->iif = coa->ifindex;
-+ hai->current_coa->addr = coa->addr;
-+ mn_update_coa_lifetime(hai->current_coa, coa);
- break;
- case MN_HO_RETURN_HOME:
-- hai->primary_coa.iif = rtr->ifindex;
-- hai->primary_coa.addr = hai->hoa.addr;
-+ hai->current_coa->iif = rtr->ifindex;
-+ hai->current_coa->addr = hai->hoa.addr;
- break;
- default:
- return;
-@@ -2311,14 +3185,20 @@ int mn_movement_event(struct movement_ev
- return 0;
- }
- dhaad_stop(hai);
-- mn_chk_ho_verdict(hai, event);
-+ if (hai->reg_mcoa)
-+ mcoa_mn_chk_ho_verdict(hai, event);
-+ else
-+ mn_chk_ho_verdict(hai, event);
- } else {
- if (event->event_type == ME_COA_EXPIRED)
- mn_rr_delete_co(&event->coa->addr);
- list_for_each(lh, &home_addr_list) {
- hai = list_entry(lh,
- struct home_addr_info, list);
-- mn_chk_ho_verdict(hai, event);
-+ if (hai->reg_mcoa)
-+ mcoa_mn_chk_ho_verdict(hai, event);
-+ else
-+ mn_chk_ho_verdict(hai, event);
- }
- }
- }
-@@ -2397,7 +3277,9 @@ void mn_start_ro(struct in6_addr *cn, st
- "from %x:%x:%x:%x:%x:%x:%x:%x\n",
- NIP6ADDR(cn), NIP6ADDR(hoa));
-
-- bule = bul_get(NULL, hoa, cn);
-+ bule = bul_get(NULL, hoa, cn,
-+ hai->reg_mcoa?
-+ get_bid_from_ifindex(iif):MCOA_NO_BID);
-
- if (bule) {
- /* If BUL entry exists, RR is done or in progress */
-@@ -2405,7 +3287,9 @@ void mn_start_ro(struct in6_addr *cn, st
- return;
- }
-
-- bule = create_bule(hoa, cn);
-+ bule = create_bule(hoa, cn,
-+ hai->reg_mcoa?
-+ get_bid_from_ifindex(iif):MCOA_NO_BID);
- if (!bule) {
- MDBG("Malloc failed at starting of RO\n");
- pthread_rwlock_unlock(&mn_lock);
-@@ -2419,6 +3303,18 @@ void mn_start_ro(struct in6_addr *cn, st
- bule->coa_changed = -1;
- bule->home = hai;
- bule->rr.state = RR_NOT_STARTED;
-+ bule->priority = get_prio_from_bid(bule->bid);
-+ /* MCoA TODO2
-+ * At the moment we prevent MIPL from installing rules for
-+ * this entry
-+ */
-+ bule->rules = 1;
-+ /* MCoA TODO2
-+ * Support for CN
-+ * The table index must be filled with
-+ * mcoa_mn_init_rt_table(bule)
-+ */
-+ bule->table = RT6_TABLE_MIP6;
-
- mn_reset_ro_bule(bule);
-
-@@ -2451,7 +3347,10 @@ static void mn_recv_brr(const struct ip6
- hoa = in->dst;
- pthread_rwlock_wrlock(&mn_lock);
- /* Do we have BUL entry for cn? If not, drop. */
-- if ((e = bul_get(NULL, hoa, cn)) == NULL) {
-+ /* MCoA TODO2
-+ * get BID from BRR BUI option
-+ */
-+ if ((e = bul_get(NULL, hoa, cn, get_bid_from_ifindex(iif))) == NULL) {
- pthread_rwlock_unlock(&mn_lock);
- return;
- }
-@@ -2499,7 +3398,11 @@ static void mn_recv_be(const struct ip6_
- hoa = in->dst;
-
- /* Do we have BUL entry for cn? If not, drop. */
-- if ((e = bul_get(NULL, hoa, cn)) == NULL || e->type != BUL_ENTRY)
-+ /* MCoA TODO2
-+ * get BID from BUI option in BERROR
-+ */
-+ if ((e = bul_get(NULL, hoa, cn, get_bid_from_ifindex(iif))) == NULL
-+ || e->type != BUL_ENTRY)
- goto out;
-
- clock_gettime(CLOCK_REALTIME, &now);
-diff -r 82fcd4bea972 src/mn.h
---- a/src/mn.h Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/mn.h Fri Jan 11 17:02:25 2008 +0100
-@@ -52,6 +52,7 @@ struct ha_candidate_list {
- #define NEMO_FWD_BLOCK 0x10
-
- struct mn_addr {
-+ struct list_head list;
- struct in6_addr addr;
- int iif;
- struct timespec timestamp;
-@@ -75,7 +76,8 @@ struct home_addr_info {
- uint8_t home_plen;
- struct in6_addr home_prefix;
- struct hash bul; /* Binding Update List */
-- struct mn_addr primary_coa;
-+ struct mn_addr *current_coa; /* MCoA: pointer to a member of mcoa */
-+ struct list_head mcoa; /* MCoA: list of all active CoAs */
- struct list_head ro_policies;
- struct ha_candidate_list ha_list;
- struct in6_addr ha_addr;
-@@ -84,9 +86,11 @@ struct home_addr_info {
- int if_tunnel;
- int if_home;
- int if_block;
-+ int table; /* MCoA: routing table number where routes are stored */
- short hwalen;
- uint8_t altcoa;
- uint16_t mob_rtr;
-+ uint8_t reg_mcoa;
- char name[IF_NAMESIZE];
- int mnp_count;
- struct list_head mob_net_prefixes;
-diff -r 82fcd4bea972 src/movement.c
---- a/src/movement.c Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/movement.c Fri Jan 11 17:02:25 2008 +0100
-@@ -165,7 +165,7 @@ static void md_prefix_rule_del(struct pr
- struct in6_addr prefix;
- ipv6_addr_prefix(&prefix, &p->ple_prefix, p->ple_plen);
- rule_del(NULL, RT6_TABLE_MAIN, IP6_RULE_PRIO_MIP6_COA_OUT,
-- RTN_UNICAST, &prefix, p->ple_plen,
-+ 0, RTN_UNICAST, &prefix, p->ple_plen,
- &in6addr_any, 0, 0);
- }
-
-@@ -312,10 +312,10 @@ static void md_expire_router(struct md_i
-
- static void md_block_rule_del(struct md_inet6_iface *iface)
- {
-- rule_del(NULL, 0, IP6_RULE_PRIO_MIP6_BLOCK_HOA, RTN_BLACKHOLE,
-+ rule_del(NULL, 0, IP6_RULE_PRIO_MIP6_BLOCK_HOA, 0, RTN_BLACKHOLE,
- &in6addr_any, 0, &in6addr_any, 0, 0);
-- rule_del(NULL, RT6_TABLE_MAIN, IP6_RULE_PRIO_MIP6_COA_OUT, RTN_UNICAST,
-- &in6addr_any, 128, &in6addr_any, 0, 0);
-+ rule_del(NULL, RT6_TABLE_MAIN, IP6_RULE_PRIO_MIP6_COA_OUT, 0,
-+ RTN_UNICAST, &in6addr_any, 128, &in6addr_any, 0, 0);
- iface->iface_flags &= ~MD_BLOCK_TRAFFIC;
- }
-
-@@ -1290,7 +1290,7 @@ static void md_prefix_rule_add(struct pr
- struct in6_addr prefix;
- ipv6_addr_prefix(&prefix, &p->ple_prefix, p->ple_plen);
- rule_add(NULL, RT6_TABLE_MAIN, IP6_RULE_PRIO_MIP6_COA_OUT,
-- RTN_UNICAST, &prefix, p->ple_plen,
-+ 0, RTN_UNICAST, &prefix, p->ple_plen,
- &in6addr_any, 0, 0);
- }
-
-@@ -1361,13 +1361,13 @@ static int md_block_rule_add(struct md_i
- iface->iface_flags |= MD_BLOCK_TRAFFIC;
- /* Allow DAD probes and RS messages */
- rule_add(NULL, RT6_TABLE_MAIN,
-- IP6_RULE_PRIO_MIP6_COA_OUT, RTN_UNICAST,
-+ IP6_RULE_PRIO_MIP6_COA_OUT, 0, RTN_UNICAST,
- &in6addr_any, 128, &in6addr_any, 0, 0);
- /* drop outgoing global traffic until DAD has been performed
- on CoA to make routing and tunnel end-point updates atomic
- during handoff */
- return rule_add(NULL, 0,
-- IP6_RULE_PRIO_MIP6_BLOCK_HOA, RTN_BLACKHOLE,
-+ IP6_RULE_PRIO_MIP6_BLOCK_HOA, 0, RTN_BLACKHOLE,
- &in6addr_any, 0, &in6addr_any, 0, 0);
- }
-
-diff -r 82fcd4bea972 src/mpdisc_ha.c
---- a/src/mpdisc_ha.c Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/mpdisc_ha.c Fri Jan 11 17:02:25 2008 +0100
-@@ -68,7 +68,7 @@ static inline struct mpa_entry *mpa_get(
- const struct in6_addr *hoa)
-
- {
-- return hash_get(&mpa_hash, ha, hoa);
-+ return hash_get(&mpa_hash, ha, hoa, 0);
- }
-
- /* HA functions */
-@@ -214,7 +214,7 @@ void mpd_cancel_mpa(const struct in6_add
- pthread_mutex_lock(&mpa_lock);
- e = mpa_get(ha, hoa);
- if (e != NULL) {
-- hash_delete(&mpa_hash, &e->ha, &e->hoa);
-+ hash_delete(&mpa_hash, &e->ha, &e->hoa, 0);
- if (tsisset(e->delay))
- del_task(&e->tqe);
- free(e);
-@@ -239,7 +239,7 @@ int mpd_start_mpa(const struct in6_addr
- memset(e, 0, sizeof(struct mpa_entry));
- e->ha = *ha;
- e->hoa = *hoa;
-- if (hash_add(&mpa_hash, e, &e->ha, &e->hoa)) {
-+ if (hash_add(&mpa_hash, e, &e->ha, &e->hoa, NULL)) {
- free(e);
- goto out;
- }
-diff -r 82fcd4bea972 src/mpdisc_mn.c
---- a/src/mpdisc_mn.c Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/mpdisc_mn.c Fri Jan 11 17:02:25 2008 +0100
-@@ -65,7 +65,7 @@ static inline struct mps_entry *mps_get(
- static inline struct mps_entry *mps_get(const struct in6_addr *hoa,
- const struct in6_addr *ha)
- {
-- return hash_get(&mps_hash, hoa, ha);
-+ return hash_get(&mps_hash, hoa, ha, 0);
- }
-
- #ifdef ENABLE_VT
-@@ -116,7 +116,7 @@ void mpd_cancel_mps(const struct in6_add
- e = mps_get(hoa, ha);
- if (e != NULL) {
- dbg("canceling MPS\n");
-- hash_delete(&mps_hash, &e->hoa, &e->ha);
-+ hash_delete(&mps_hash, &e->hoa, &e->ha, 0);
- if (tsisset(e->delay))
- del_task(&e->tqe);
- free(e);
-@@ -175,7 +175,7 @@ int mpd_schedule_first_mps(const struct
- memset(e, 0, sizeof(struct mps_entry));
- e->hoa = *hoa;
- e->ha = *ha;
-- if (hash_add(&mps_hash, e, &e->hoa, &e->ha)) {
-+ if (hash_add(&mps_hash, e, &e->hoa, &e->ha, NULL)) {
- free(e);
- goto out;
- }
-diff -r 82fcd4bea972 src/ndisc.h
---- a/src/ndisc.h Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/ndisc.h Fri Jan 11 17:02:25 2008 +0100
-@@ -21,6 +21,7 @@ static inline short nd_get_l2addr_len(un
- return 1;
- /* supported virtual devices */
- case ARPHRD_SIT:
-+ return 4;
- case ARPHRD_TUNNEL6:
- case ARPHRD_PPP:
- case ARPHRD_IPGRE:
-diff -r 82fcd4bea972 src/policy.c
---- a/src/policy.c Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/policy.c Fri Jan 11 17:02:25 2008 +0100
-@@ -47,6 +47,25 @@ pthread_rwlock_t policy_lock;
- pthread_rwlock_t policy_lock;
- struct hash policy_bind_acl_hash;
- int def_bind_policy = IP6_MH_BAS_PROHIBIT;
-+
-+/**
-+ * default_mcoa_reg - Check if MCoA reg is allowed
-+ * @remote_hoa: remote MN's home address
-+ *
-+ * Returns 0 if not allowed, 1 if allowed.
-+ **/
-+int default_mcoa_reg(const struct in6_addr *remote_hoa)
-+{
-+ struct policy_bind_acl_entry *acl;
-+ int ret = 1;
-+
-+ pthread_rwlock_rdlock(&policy_lock);
-+ acl = hash_get(&policy_bind_acl_hash, NULL, remote_hoa, 0);
-+ if (!conf.HaAcceptMCoAReg || (acl && !acl->mcoa_reg))
-+ ret = 0;
-+ pthread_rwlock_unlock(&policy_lock);
-+ return ret;
-+}
-
- /**
- * default_best_iface - select best interface during handoff
-@@ -148,7 +167,7 @@ int default_discard_binding(const struct
- return IP6_MH_BAS_MR_OP_NOT_PERMITTED;
-
- pthread_rwlock_rdlock(&policy_lock);
-- acl = hash_get(&policy_bind_acl_hash, NULL, remote_hoa);
-+ acl = hash_get(&policy_bind_acl_hash, NULL, remote_hoa, 0);
- if (acl != NULL) {
- ret = acl->bind_policy;
- if (ret < IP6_MH_BAS_UNSPECIFIED &&
-@@ -213,8 +232,16 @@ int default_accept_inet6_iface(int iif)
- struct net_iface *nif;
- nif = list_entry(list, struct net_iface, list);
- if (nif->ifindex == iif) {
-- if (is_if_mn(nif))
-- return nif->mn_if_preference;
-+ if (is_if_mn(nif)) {
-+ /* MCoA
-+ * Return the BID Priority if the
-+ * interface preference is 0
-+ */
-+ if(nif->mn_if_preference)
-+ return nif->mn_if_preference;
-+ else
-+ return nif->mn_if_bidprio;
-+ }
- return 0;
- }
- }
-@@ -259,7 +286,7 @@ int default_get_mnp_count(const struct i
- int ret = 0;
- struct policy_bind_acl_entry *acl;
- pthread_rwlock_rdlock(&policy_lock);
-- acl = hash_get(&policy_bind_acl_hash, NULL, hoa);
-+ acl = hash_get(&policy_bind_acl_hash, NULL, hoa, 0);
- if (acl != NULL)
- ret = acl->mnp_count;
- pthread_rwlock_unlock(&policy_lock);
-@@ -275,7 +302,7 @@ int default_get_mnps(const struct in6_ad
- struct policy_bind_acl_entry *acl;
-
- pthread_rwlock_rdlock(&policy_lock);
-- acl = hash_get(&policy_bind_acl_hash, NULL, hoa);
-+ acl = hash_get(&policy_bind_acl_hash, NULL, hoa, 0);
- if (acl != NULL) {
- struct list_head *l;
- list_for_each(l, &acl->mob_net_prefixes) {
-@@ -314,7 +341,7 @@ static int policy_bind_acl_add(struct po
- static int policy_bind_acl_add(struct policy_bind_acl_entry *acl)
- {
- int err;
-- err = hash_add(&policy_bind_acl_hash, acl, NULL, &acl->hoa);
-+ err = hash_add(&policy_bind_acl_hash, acl, NULL, &acl->hoa, NULL);
- if (!err) {
- list_del(&acl->list);
- }
-diff -r 82fcd4bea972 src/policy.h
---- a/src/policy.h Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/policy.h Fri Jan 11 17:02:25 2008 +0100
-@@ -6,7 +6,13 @@
- #include
- #include "list.h"
-
--#define POL_MN_IF_DEF_PREFERENCE 5
-+/* MCoA
-+ * Changed POL_MN_IF_DEF_PREFERENCE from 5 to 0
-+ */
-+#define POL_MN_IF_DEF_PREFERENCE 0
-+#define POL_MN_IF_DEF_BID 0
-+#define POL_MN_IF_DEF_BID_PRIORITY 0
-+#define POL_MN_IF_DEF_RELIABLE 1
-
- struct ip6_mh_binding_update;
- struct nd_router_advert;
-@@ -17,9 +23,18 @@ struct policy_bind_acl_entry {
- struct in6_addr hoa;
- int plen;
- int bind_policy;
-+ int mcoa_reg;
- int mnp_count;
- struct list_head mob_net_prefixes;
- };
-+
-+/**
-+ * default_mcoa_reg - Check if MCoA registration is allowed
-+ * @remote_hoa: remote MN's home address
-+ *
-+ * Returns 0 if not allowed, 1 if allowed.
-+ **/
-+int default_mcoa_reg(const struct in6_addr *remote_hoa);
-
- /**
- * default_best_iface - select best interface during handoff
-diff -r 82fcd4bea972 src/retrout.c
---- a/src/retrout.c Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/retrout.c Fri Jan 11 17:02:25 2008 +0100
-@@ -151,7 +151,7 @@ static struct rrlentry *rre_create(int t
- rre->own2 = *own2;
- rre->iif = iif;
-
-- if (hash_add(&rrl_hash, rre, &rre->own1, &rre->peer) < 0) {
-+ if (hash_add(&rrl_hash, rre, &rre->own1, &rre->peer, NULL) < 0) {
- rrl_delete(rre);
- return NULL;
- }
-@@ -168,7 +168,7 @@ static struct rrlentry *rrl_get(int type
-
- assert(our_addr);
-
-- rre = (struct rrlentry *)hash_get(&rrl_hash, our_addr, peer_addr);
-+ rre = (struct rrlentry *)hash_get(&rrl_hash, our_addr, peer_addr, 0);
-
- if (rre != NULL && rre->type != type)
- return NULL;
-@@ -188,7 +188,7 @@ static void rrl_delete(struct rrlentry *
- TRACE;
-
- del_task(&rre->tqe);
-- hash_delete(&rrl_hash, &rre->own1, &rre->peer);
-+ hash_delete(&rrl_hash, &rre->own1, &rre->peer, 0);
-
- if (rre->type == COT_ENTRY) {
- struct list_head *list, *n;
-@@ -629,7 +629,7 @@ int mn_rr_error_check(const struct in6_a
- const struct in6_addr *peer,
- struct in6_addr *hoa)
- {
-- struct rrlentry *rre = hash_get(&rrl_hash, own, peer);
-+ struct rrlentry *rre = hash_get(&rrl_hash, own, peer, 0);
-
- if (rre == NULL || !rre->wait)
- return 0;
-@@ -694,7 +694,11 @@ static void mn_recv_cot(const struct ip6
- struct addr_holder *ah;
-
- ah = list_entry(list, struct addr_holder, list);
-- bule = bul_get(NULL, &ah->addr, cn_addr);
-+ /* MCoA TODO2
-+ * MCoA does not work with RR
-+ * At the moment the first entry that match is chosen
-+ */
-+ bule = bul_get(NULL, &ah->addr, cn_addr, MCOA_NO_BID);
-
- if (bule == NULL || bule->type != BUL_ENTRY ||
- !IN6_ARE_ADDR_EQUAL(&rre_co->own1, &bule->coa)) {
-@@ -774,7 +778,11 @@ static void mn_recv_hot(const struct ip6
- pthread_rwlock_unlock(&mn_lock);
- return;
- }
-- bule = bul_get(NULL, home_addr, cn_addr);
-+ /* MCoA TODO2
-+ * MCoA does not work with RR
-+ * At the moment the first entry that match is chosen
-+ */
-+ bule = bul_get(NULL, home_addr, cn_addr, MCOA_NO_BID);
-
- if (bule == NULL || bule->type != BUL_ENTRY) {
- rrl_delete(rre_ho);
-diff -r 82fcd4bea972 src/rtnl.c
---- a/src/rtnl.c Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/rtnl.c Fri Jan 11 17:02:25 2008 +0100
-@@ -299,7 +299,7 @@ int route_del(int oif, uint8_t table, ui
- }
-
- static int rule_mod(const char *iface, int cmd, uint8_t table,
-- uint32_t priority, uint8_t action,
-+ uint32_t priority, uint32_t fwmark, uint8_t action,
- const struct in6_addr *src, int src_plen,
- const struct in6_addr *dst, int dst_plen, int flags)
- {
-@@ -331,6 +331,8 @@ static int rule_mod(const char *iface, i
- addattr_l(n, sizeof(buf), RTA_SRC, src, sizeof(*src));
- if (priority)
- addattr32(n, sizeof(buf), RTA_PRIORITY, priority);
-+ if (fwmark)
-+ addattr32(n, sizeof(buf), RTA_PROTOINFO, fwmark);
- if (iface)
- addattr_l(n, sizeof(buf), RTA_IIF, iface, strlen(iface) + 1);
-
-@@ -349,12 +351,12 @@ static int rule_mod(const char *iface, i
- * negative otherwise.
- **/
- int rule_add(const char *iface, uint8_t table,
-- uint32_t priority, uint8_t action,
-+ uint32_t priority, uint32_t fwmark, uint8_t action,
- const struct in6_addr *src, int src_plen,
- const struct in6_addr *dst, int dst_plen, int flags)
- {
- return rule_mod(iface, RTM_NEWRULE, table,
-- priority, action,
-+ priority, fwmark, action,
- src, src_plen, dst, dst_plen, flags);
- }
-
-@@ -370,12 +372,12 @@ int rule_add(const char *iface, uint8_t
- * otherwise.
- **/
- int rule_del(const char *iface, uint8_t table,
-- uint32_t priority, uint8_t action,
-+ uint32_t priority, uint32_t fwmark, uint8_t action,
- const struct in6_addr *src, int src_plen,
- const struct in6_addr *dst, int dst_plen, int flags)
- {
- return rule_mod(iface, RTM_DELRULE, table,
-- priority, action,
-+ priority, fwmark, action,
- src, src_plen, dst, dst_plen, flags);
- }
-
-diff -r 82fcd4bea972 src/rtnl.h
---- a/src/rtnl.h Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/rtnl.h Fri Jan 11 17:02:25 2008 +0100
-@@ -17,11 +17,14 @@
- #define IP6_RT_PRIO_ADDRCONF 256
-
- #define IP6_RULE_PRIO_MIP6_MNP_IN 1000
--#define IP6_RULE_PRIO_MIP6_HOA_OUT 1001
--#define IP6_RULE_PRIO_MIP6_COA_OUT 1002
--#define IP6_RULE_PRIO_MIP6_BLOCK 1003
--#define IP6_RULE_PRIO_MIP6_BLOCK_HOA 1004
--#define IP6_RULE_PRIO_MIP6_FWD 1005
-+#define IP6_RULE_PRIO_MIP6_HOA_OUT_MCOA 1001
-+#define IP6_RULE_PRIO_MIP6_HOA_OUT 1002
-+#define IP6_RULE_PRIO_MIP6_COA_OUT 1003
-+#define IP6_RULE_PRIO_MIP6_BLOCK 1004
-+#define IP6_RULE_PRIO_MIP6_BLOCK_HOA 1005
-+#define IP6_RULE_PRIO_MIP6_FWD_FWM 1006
-+#define IP6_RULE_PRIO_MIP6_FWD_MCOA 1007
-+#define IP6_RULE_PRIO_MIP6_FWD 1008
-
- static inline int rtnl_route_open(struct rtnl_handle *rth,
- unsigned subscriptions)
-@@ -74,12 +77,12 @@ int route_del(int oif, uint8_t table, ui
- const struct in6_addr *gateway);
-
- int rule_add(const char *iface, uint8_t table,
-- uint32_t priority, uint8_t action,
-+ uint32_t priority, uint32_t fwmark, uint8_t action,
- const struct in6_addr *src, int src_plen,
- const struct in6_addr *dst, int dst_plen, int flags);
-
- int rule_del(const char *iface, uint8_t table,
-- uint32_t priority, uint8_t action,
-+ uint32_t priority, uint32_t fwmark, uint8_t action,
- const struct in6_addr *src, int src_plen,
- const struct in6_addr *dst, int dst_plen,int flags);
-
-diff -r 82fcd4bea972 src/scan.l
---- a/src/scan.l Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/scan.l Fri Jan 11 17:02:25 2008 +0100
-@@ -137,7 +137,15 @@ MnDiscardHaParamProb { return MNDISCARD
- MnDiscardHaParamProb { return MNDISCARDHAPARAMPROB; }
- OptimisticHandoff { return OPTIMISTICHANDOFF; }
- HaAcceptMobRtr { return HAACCEPTMOBRTR; }
-+HaAcceptMCoAReg { return HAACCEPTMCOAREG; }
-+MCoAReg { return MCOAREG; }
-+NoMCoAReg { return NOMCOAREG; }
- IsMobRtr { return ISMOBRTR; }
-+Bid { return BID; }
-+BidPriority { return BIDPRIORITY; }
-+Reliable { return RELIABLE; }
-+RegMultipleCoA { return REGMULTIPLECOA; }
-+IfMultipleCoA { return IFMULTIPLECOA; }
- HaServedPrefix { return HASERVEDPREFIX; }
- HomePrefix { return HOMEPREFIX; }
- MobRtrUseExplicitMode { return MOBRTRUSEEXPLICITMODE; }
-diff -r 82fcd4bea972 src/tunnelctl.c
---- a/src/tunnelctl.c Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/tunnelctl.c Fri Jan 11 17:02:25 2008 +0100
-@@ -157,7 +157,7 @@ static int __tunnel_del(struct mip6_tnl
- if (tnl->users == 0) {
- struct ifreq ifr;
- list_del(&tnl->list);
-- hash_delete(&tnl_hash, &tnl->parm.laddr, &tnl->parm.raddr);
-+ hash_delete(&tnl_hash, &tnl->parm.laddr, &tnl->parm.raddr, 0);
- strcpy(ifr.ifr_name, tnl->parm.name);
- if ((res = ioctl(tnl_fd, SIOCDELTUNNEL, &ifr)) < 0) {
- TDBG("SIOCDELTUNNEL failed status %d %s\n",
-@@ -249,7 +249,7 @@ static struct mip6_tnl *__tunnel_add(str
- TDBG("no device called %s\n", tnl->parm.name);
- goto err;
- }
-- if (hash_add(&tnl_hash, tnl, &tnl->parm.laddr, &tnl->parm.raddr) < 0)
-+ if (hash_add(&tnl_hash, tnl, &tnl->parm.laddr, &tnl->parm.raddr, NULL) < 0)
- goto err;
-
- list_add_tail(&tnl->list, &tnl_list);
-@@ -287,7 +287,7 @@ int tunnel_add(struct in6_addr *local,
- int res;
-
- pthread_mutex_lock(&tnl_lock);
-- if ((tnl = hash_get(&tnl_hash, local, remote)) != NULL) {
-+ if ((tnl = hash_get(&tnl_hash, local, remote, 0)) != NULL) {
- tnl->users++;
- TDBG("tunnel %s (%d) from %x:%x:%x:%x:%x:%x:%x:%x "
- "to %x:%x:%x:%x:%x:%x:%x:%x user count increased to %d\n",
-@@ -339,9 +339,10 @@ static int __tunnel_mod(struct mip6_tnl
- errno, strerror(errno));
- return -1;
- }
-- hash_delete(&tnl_hash, &tnl->parm.laddr, &tnl->parm.raddr);
-+ hash_delete(&tnl_hash, &tnl->parm.laddr, &tnl->parm.raddr, 0);
- memcpy(&tnl->parm, &parm, sizeof(struct ip6_tnl_parm));
-- if (hash_add(&tnl_hash, tnl, &tnl->parm.laddr, &tnl->parm.raddr) < 0) {
-+ if (hash_add(&tnl_hash, tnl, &tnl->parm.laddr,
-+ &tnl->parm.raddr, NULL) < 0) {
- free(tnl);
- return -1;
- }
-@@ -387,7 +388,7 @@ int tunnel_mod(int ifindex,
- old = get_tnl(ifindex);
- assert(old != NULL);
-
-- if ((new = hash_get(&tnl_hash, local, remote)) != NULL) {
-+ if ((new = hash_get(&tnl_hash, local, remote, 0)) != NULL) {
- if (new != old) {
- new->users++;
- TDBG("tunnel %s (%d) from %x:%x:%x:%x:%x:%x:%x:%x "
-@@ -448,7 +449,7 @@ static int tnl_cleanup(void *data, void
- {
- struct mip6_tnl *tnl = (struct mip6_tnl *) data;
- list_del(&tnl->list);
-- hash_delete(&tnl_hash, &tnl->parm.laddr, &tnl->parm.raddr);
-+ hash_delete(&tnl_hash, &tnl->parm.laddr, &tnl->parm.raddr, 0);
- free(tnl);
- return 0;
- }
-diff -r 82fcd4bea972 src/vt.c
---- a/src/vt.c Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/vt.c Fri Jan 11 17:02:25 2008 +0100
-@@ -428,6 +428,12 @@ static int bul_vt_dump(void *data, void
- fprintf(vh->vh_stream, " last_coa %x:%x:%x:%x:%x:%x:%x:%x",
- NIP6ADDR(&bule->last_coa));
-
-+ if (bule->bid) {
-+ fprintf(vh->vh_stream, " BID %d", bule->bid);
-+ fprintf(vh->vh_stream, " BidPriority %d",
-+ bule->priority);
-+ }
-+
- fprintf(vh->vh_stream, "\n");
-
- if (!(bule->flags & IP6_MH_BU_HOME)) {
-@@ -579,6 +585,11 @@ static int bcache_vt_dump(void *data, vo
-
- fprintf(vh->vh_stream, " coa %x:%x:%x:%x:%x:%x:%x:%x",
- NIP6ADDR(&bce->coa));
-+
-+ if (bce->bid) {
-+ fprintf(vh->vh_stream, " BID %d", bce->bid);
-+ fprintf(vh->vh_stream, " BidPriority %d", bce->priority);
-+ }
-
- if (vh->vh_opt.verbose == VT_BOOL_TRUE)
- fprintf(vh->vh_stream, " nonce %u", bce->nonce_coa);
-diff -r 82fcd4bea972 src/xfrm.c
---- a/src/xfrm.c Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/xfrm.c Fri Jan 11 17:02:25 2008 +0100
-@@ -56,7 +56,7 @@
- #include "conf.h"
- #include "ipsec.h"
-
--#define XFRM_DEBUG_LEVEL 1
-+#define XFRM_DEBUG_LEVEL 2
-
- #if XFRM_DEBUG_LEVEL >= 1
- #define XDBG dbg
-@@ -1555,7 +1555,7 @@ static int xfrm_bule_bce_update(const st
- int res = -1;
- pthread_rwlock_rdlock(&mn_lock);
- if ((hai = mn_get_home_addr(our_addr)) != NULL) {
-- if ((e = bul_get(hai, NULL, peer_addr)) != NULL) {
-+ if ((e = bul_get(hai, NULL, peer_addr, MCOA_NO_BID)) != NULL) {
- if (e->type == BUL_ENTRY &&
- !_xfrm_add_bule_bce(our_addr, peer_addr, replace))
- res = 0;
-@@ -1582,30 +1582,34 @@ int xfrm_add_bce(const struct in6_addr *
- int xfrm_add_bce(const struct in6_addr *our_addr,
- const struct in6_addr *peer_addr,
- const struct in6_addr *coa,
-- int replace)
-+ int replace,
-+ int create)
- {
- struct xfrm_selector sel;
-
- /* Create policy for outbound RO data traffic */
-- set_selector(peer_addr, our_addr, 0, 0, 0, 0, &sel);
-- if (xfrm_state_add(&sel, IPPROTO_ROUTING, coa, replace, 0)){
-- /*
-- * WORKAROUND
-- * In some cases, MN fail to add it because of the state
-- * inserted by kernel when notifying aquire. So,update it.
-- */
-- if (xfrm_state_add(&sel, IPPROTO_ROUTING, coa, 1, 0))
-- return -1;
-- }
-- set_selector(our_addr, peer_addr, 0, 0, 0, 0, &sel);
-- if (xfrm_state_add(&sel, IPPROTO_DSTOPTS, coa, replace, 0)){
-- /*
-- * WORKAROUND
-- * In some cases, MN fail to add it because of the state
-- * inserted by kernel when notifying aquire. So,update it.
-- */
-- if (xfrm_state_add(&sel, IPPROTO_DSTOPTS, coa, 1, 0))
-- return -1;
-+ if (create || replace) {
-+ set_selector(peer_addr, our_addr, 0, 0, 0, 0, &sel);
-+ if (xfrm_state_add(&sel, IPPROTO_ROUTING, coa, replace, 0)){
-+ /*
-+ * WORKAROUND
-+ * In some cases, MN fail to add it because of the state
-+ * inserted by kernel when notifying aquire. So,update it.
-+ */
-+ if (xfrm_state_add(&sel, IPPROTO_ROUTING, coa, 1, 0))
-+ return -1;
-+ }
-+
-+ set_selector(our_addr, peer_addr, 0, 0, 0, 0, &sel);
-+ if (xfrm_state_add(&sel, IPPROTO_DSTOPTS, coa, replace, 0)){
-+ /*
-+ * WORKAROUND
-+ * In some cases, MN fail to add it because of the state
-+ * inserted by kernel when notifying aquire. So,update it.
-+ */
-+ if (xfrm_state_add(&sel, IPPROTO_DSTOPTS, coa, 1, 0))
-+ return -1;
-+ }
- }
- if (is_mn() && !xfrm_bule_bce_update(our_addr, peer_addr, replace))
- return 0;
-@@ -1614,7 +1618,8 @@ int xfrm_add_bce(const struct in6_addr *
- _ha_mn_ipsec_pol_mod, NULL) < 0)
- return -1;
- }
-- _xfrm_add_bce(our_addr, peer_addr, replace);
-+ if (create || replace)
-+ _xfrm_add_bce(our_addr, peer_addr, replace);
- return 0;
- }
-
-@@ -1643,7 +1648,7 @@ void xfrm_del_bce(const struct in6_addr
- /* for MN-MN communications, checking BUL to insert RO policy */
- pthread_rwlock_rdlock(&mn_lock);
- if ((hai = mn_get_home_addr(our_addr)) != NULL) {
-- if ((e = bul_get(hai, NULL, peer_addr)) != NULL) {
-+ if ((e = bul_get(hai, NULL, peer_addr, MCOA_NO_BID)) != NULL) {
- if (e->type == BUL_ENTRY)
- _xfrm_add_bule_bce(our_addr, peer_addr, 0);
- }
-@@ -1736,7 +1741,7 @@ static int _xfrm_bce_reset(struct bulent
- static int _xfrm_bce_reset(struct bulentry *bule)
- {
- /* for MN - MN communication */
-- struct bcentry *bce = bcache_get(&bule->hoa, &bule->peer_addr);
-+ struct bcentry *bce = bcache_get(&bule->hoa, &bule->peer_addr, MCOA_NO_BID);
- int res = 0;
- if (!bce)
- return 0;
-@@ -1754,21 +1759,34 @@ static int _xfrm_del_bule_data(struct bu
- static int _xfrm_del_bule_data(struct bulentry *bule)
- {
- struct xfrm_selector sel;
-+ int bule_exists = mcoa_bule_count(bule);
- int prio;
-
-- set_selector(&bule->peer_addr, &bule->hoa, 0, 0, 0, 0, &sel);
-- xfrm_state_del(IPPROTO_DSTOPTS, &sel);
-+ /* MCoA
-+ * XFRM states are deleted only when the last BULE for
-+ * the same peer is deleted, or when returning home
-+ */
-+ if (!bule_exists || !bule->home->reg_mcoa || bule->home->at_home) {
-+ XDBG2("Last entry for the peer, deleting XFRM states\n");
-+ set_selector(&bule->peer_addr, &bule->hoa, 0, 0, 0, 0, &sel);
-+ xfrm_state_del(IPPROTO_DSTOPTS, &sel);
-+ }
-
- if (bule->home->home_reg_status != HOME_REG_NONE &&
- mn_has_cn_ro_pol(bule)) {
- struct xfrm_user_tmpl tmpl;
- create_trig_dstopt_tmpl(&tmpl, &bule->peer_addr, &bule->hoa);
-+ /* MCoA: replaced bule->home->if_tunnel with bule->if_tunnel */
- set_selector(&bule->peer_addr, &bule->hoa,
-- 0, 0, 0, bule->home->if_tunnel, &sel);
-+ 0, 0, 0, bule->if_tunnel, &sel);
- xfrm_mip_policy_add(&sel, 1, XFRM_POLICY_OUT,
- XFRM_POLICY_ALLOW, MIP6_PRIO_RO_TRIG, &tmpl, 1);
-- } else
-- _mn_bule_ro_pol_del(bule, bule->home->if_tunnel);
-+ } else if(!bule_exists || !bule->home->reg_mcoa || bule->home->at_home) {
-+ /* MCoA: policies deleted only if this is the last BULE
-+ * for the same peer, or when returning home */
-+ /* MCoA: replaced bule->home->if_tunnel with bule->if_tunnel */
-+ _mn_bule_ro_pol_del(bule, bule->if_tunnel);
-+ }
-
- if (!(bule->flags & IP6_MH_BU_HOME))
- _xfrm_bce_reset(bule);
-@@ -1779,20 +1797,25 @@ static int _xfrm_del_bule_data(struct bu
- /* MN - CN/HA case, BU out */
- prio = (bule->flags & IP6_MH_BU_HOME ?
- MIP6_PRIO_HOME_SIG : MIP6_PRIO_RO_SIG);
-- if (bule->flags & IP6_MH_BU_ACK) {
-+ if ((bule->flags & IP6_MH_BU_ACK)
-+ && (!bule_exists || !bule->home->reg_mcoa
-+ || bule->home->at_home)) {
- set_selector(&bule->hoa, &bule->peer_addr, IPPROTO_MH,
- IP6_MH_TYPE_BACK, 0, 0, &sel);
- if (xfrm_mip_policy_add(&sel, 1, XFRM_POLICY_IN,
- XFRM_POLICY_ALLOW, prio, NULL, 0))
- return -1;
- }
-- set_selector(&bule->peer_addr, &bule->hoa, IPPROTO_MH,
-- IP6_MH_TYPE_BU, 0, 0, &sel);
-- if (xfrm_mip_policy_add(&sel, 1, XFRM_POLICY_OUT,
-- XFRM_POLICY_ALLOW, prio, NULL, 0))
-- return -1;
-+ if (!bule_exists || !bule->home->reg_mcoa
-+ || bule->home->at_home) {
-+ set_selector(&bule->peer_addr, &bule->hoa, IPPROTO_MH,
-+ IP6_MH_TYPE_BU, 0, 0, &sel);
-+ if (xfrm_mip_policy_add(&sel, 1, XFRM_POLICY_OUT,
-+ XFRM_POLICY_ALLOW, prio, NULL, 0))
-+ return -1;
-+ bule->xfrm_state &= ~BUL_XFRM_STATE_DATA;
-+ }
-
-- bule->xfrm_state &= ~BUL_XFRM_STATE_DATA;
- return 0;
- }
-
-@@ -1817,7 +1840,14 @@ void xfrm_del_bule(struct bulentry *bule
- {
- if (bule->xfrm_state & BUL_XFRM_STATE_DATA)
- _xfrm_del_bule_data(bule);
-- _xfrm_del_bule_sig(bule);
-+ /* MCoA
-+ * XFRM policies are deleted only when the last BULE for the
-+ * same peer is deleted, or when returning home
-+ */
-+ if (mcoa_bule_count(bule) == 0 || bule->home->at_home) {
-+ XDBG2("Last entry for the peer, deleting XFRM policies\n");
-+ _xfrm_del_bule_sig(bule);
-+ }
- }
-
- /* before sending BU, MN should insert policy/state only for BU/BA */
-@@ -1829,14 +1859,26 @@ int xfrm_pre_bu_add_bule(struct bulentry
- int rdata = bule->xfrm_state & BUL_XFRM_STATE_DATA;
- int prio;
- int exist = 0;
-+ int bule_count = mcoa_bule_count(bule);
-
- if (bule->flags & IP6_MH_BU_HOME) {
- struct home_addr_info *hai = bule->home;
- if (hai->home_block & HOME_LINK_BLOCK)
- xfrm_unblock_link(hai);
-- xfrm_block_link(hai);
-- if (hai->mob_rtr && !(hai->home_block & NEMO_FWD_BLOCK))
-- xfrm_block_fwd(hai);
-+ if (bule->home_block & HOME_LINK_BLOCK)
-+ xfrm_unblock_bule_link(bule);
-+ if (!hai->reg_mcoa)
-+ xfrm_block_link(hai);
-+ else
-+ xfrm_block_bule_link(bule);
-+ if (hai->mob_rtr) {
-+ if (!hai->reg_mcoa &&
-+ !(hai->home_block & NEMO_FWD_BLOCK))
-+ xfrm_block_fwd(hai);
-+ else if (hai->reg_mcoa &&
-+ !(bule->home_block & NEMO_FWD_BLOCK))
-+ bule_block_fwd(bule);
-+ }
- }
- if (IN6_ARE_ADDR_EQUAL(&bule->hoa, &bule->coa)) {
- if (rdata)
-@@ -1850,25 +1892,32 @@ int xfrm_pre_bu_add_bule(struct bulentry
- return -1;
- }
- /* MN - CN/HA case, BU out */
-- prio = (bule->flags & IP6_MH_BU_HOME ?
-- MIP6_PRIO_HOME_SIG : MIP6_PRIO_RO_SIG);
-- if (bule->flags & IP6_MH_BU_ACK) {
-- create_rh_tmpl(&tmpl);
-- set_selector(&bule->hoa, &bule->peer_addr, IPPROTO_MH,
-- IP6_MH_TYPE_BACK, 0, 0, &sel);
-- if (xfrm_mip_policy_add(&sel, rsig, XFRM_POLICY_IN,
-+ if (bule_count == 1) {
-+ /* MCoA
-+ * If another BULE already exists for this HoA/HA addr
-+ * we do not need to install the policies once again
-+ */
-+ prio = (bule->flags & IP6_MH_BU_HOME ?
-+ MIP6_PRIO_HOME_SIG : MIP6_PRIO_RO_SIG);
-+ if (bule->flags & IP6_MH_BU_ACK) {
-+ create_rh_tmpl(&tmpl);
-+ set_selector(&bule->hoa, &bule->peer_addr, IPPROTO_MH,
-+ IP6_MH_TYPE_BACK, 0, 0, &sel);
-+ if (xfrm_mip_policy_add(&sel, rsig, XFRM_POLICY_IN,
-+ XFRM_POLICY_ALLOW, prio, &tmpl, 1))
-+ return -1;
-+ }
-+ create_dstopt_tmpl(&tmpl, &bule->peer_addr, &bule->hoa);
-+ set_selector(&bule->peer_addr, &bule->hoa, IPPROTO_MH,
-+ IP6_MH_TYPE_BU, 0, 0, &sel);
-+ if (xfrm_mip_policy_add(&sel, rsig, XFRM_POLICY_OUT,
- XFRM_POLICY_ALLOW, prio, &tmpl, 1))
- return -1;
- }
-- create_dstopt_tmpl(&tmpl, &bule->peer_addr, &bule->hoa);
-- set_selector(&bule->peer_addr, &bule->hoa, IPPROTO_MH,
-- IP6_MH_TYPE_BU, 0, 0, &sel);
-- if (xfrm_mip_policy_add(&sel, rsig, XFRM_POLICY_OUT,
-- XFRM_POLICY_ALLOW, prio, &tmpl, 1))
-- return -1;
-
- if (!(bule->flags & IP6_MH_BU_HOME)) {
-- struct bcentry *bce = bcache_get(&bule->hoa, &bule->peer_addr);
-+ struct bcentry *bce = bcache_get(&bule->hoa, &bule->peer_addr,
-+ MCOA_NO_BID);
- if (bce) {
- if (bce->type > BCE_NONCE_BLOCK &&
- _xfrm_add_bce(&bule->hoa, &bule->peer_addr, 1)) {
-@@ -1879,11 +1928,16 @@ int xfrm_pre_bu_add_bule(struct bulentry
- exist = 1;
- }
- }
-- if(!exist &&_mn_bule_ro_pol_add(bule, bule->home->if_tunnel, rdata))
-+ /* MCoA: Replaced bule->home->if_tunnel with bule->if_tunnel */
-+ if(!exist && bule_count == 1
-+ && _mn_bule_ro_pol_add(bule, bule->if_tunnel, rdata))
- return -1;
- set_selector(&bule->peer_addr, &bule->hoa, 0, 0, 0, 0, &sel);
- /* XXX: acquired state is already inserted */
-- if (!(bule->flags & IP6_MH_BU_HOME)) {
-+ /* MCoA: Add the states if there is only 1 BCE for the peer,
-+ * otherwise just update the CoA
-+ */
-+ if (!(bule->flags & IP6_MH_BU_HOME) || mcoa_bule_count(bule) > 1) {
- XDBG2("%s: original rdata = %d\n", __FUNCTION__, rdata);
- rdata = 1;
- }
-@@ -1902,15 +1956,20 @@ int xfrm_post_ba_mod_bule(struct bulentr
- struct home_addr_info *hai = bule->home;
- if (hai->home_block & HOME_LINK_BLOCK)
- xfrm_unblock_link(hai);
-+ if (bule->home_block & HOME_LINK_BLOCK)
-+ xfrm_unblock_bule_link(bule);
- if (hai->home_block & NEMO_FWD_BLOCK)
- xfrm_unblock_fwd(hai);
-+ if (bule->home_block & NEMO_FWD_BLOCK)
-+ bule_unblock_fwd(bule);
- }
- /* check if XFRM policies and states have already been cleaned up */
- if (IN6_ARE_ADDR_EQUAL(&bule->hoa, &bule->coa))
- return 0;
-
- if (!(bule->flags & IP6_MH_BU_HOME)) {
-- struct bcentry *bce = bcache_get(&bule->hoa, &bule->peer_addr);
-+ struct bcentry *bce = bcache_get(&bule->hoa, &bule->peer_addr,
-+ MCOA_NO_BID);
- if (bce) {
- if (bce->type > BCE_NONCE_BLOCK &&
- _xfrm_add_bule_bce(&bule->hoa,
-@@ -1925,11 +1984,27 @@ int xfrm_post_ba_mod_bule(struct bulentr
- }
- prio = (bule->flags & IP6_MH_BU_HOME ?
- MIP6_PRIO_HOME_DATA : MIP6_PRIO_RO_BULE_DATA);
-- set_selector(&bule->peer_addr, &bule->hoa, 0, 0, 0,
-- bule->home->if_tunnel, &sel);
-- create_dstopt_tmpl(&tmpls[0], &bule->peer_addr, &bule->hoa);
-- ret = xfrm_mip_policy_add(&sel, 1, XFRM_POLICY_OUT,
-- XFRM_POLICY_ALLOW, prio, tmpls, 1);
-+
-+ /* MCoA: Replaced bule->home->if_tunnel with bule->if_tunnel */
-+ set_selector(&bule->peer_addr, &bule->hoa, 0, 0, 0,
-+ bule->if_tunnel, &sel);
-+
-+ /* MCoA TODO1: to update according to the latest draft.
-+ * When MCoA is used, do not use HAO dest. option
-+ * for traffic from the MN/MR to the HA. Tunnel packets
-+ * instead.
-+ */
-+ if(bule->home->reg_mcoa) {
-+ ret = xfrm_mip_policy_add(&sel, 1, XFRM_POLICY_OUT,
-+ XFRM_POLICY_ALLOW, prio,
-+ NULL, 0);
-+ } else {
-+ create_dstopt_tmpl(&tmpls[0], &bule->peer_addr, &bule->hoa);
-+ ret = xfrm_mip_policy_add(&sel, 1, XFRM_POLICY_OUT,
-+ XFRM_POLICY_ALLOW, prio,
-+ tmpls, 1);
-+ }
-+
- if (ret)
- XDBG("failed to insert outbound policy\n");
-
-@@ -2126,6 +2201,31 @@ void xfrm_cleanup(void)
- xfrm_cn_cleanup();
- }
-
-+/* blocking all payload packets from MN via a specific interface */
-+int xfrm_block_bule_link(struct bulentry *bule)
-+{
-+ int ret = 0;
-+ struct xfrm_selector sel;
-+ bule->home_block |= HOME_LINK_BLOCK;
-+ /* allow MN to send NA messages */
-+ /* RK: such policy is already installed in xfrm_cn_init at startup,
-+ * so we update it (update field to 1) */
-+ set_selector(&in6addr_any, &in6addr_any, IPPROTO_ICMPV6,
-+ ND_NEIGHBOR_ADVERT, 0, bule->if_coa, &sel);
-+ if ((ret = xfrm_mip_policy_add(&sel, 1 /* update */, XFRM_POLICY_OUT,
-+ XFRM_POLICY_ALLOW,
-+ MIP6_PRIO_HOME_SIG_ANY, NULL, 0)))
-+ return ret;
-+
-+ /* block any packets from HoA to the CN */
-+ set_selector(&in6addr_any, &in6addr_any, 0, 0, 0, bule->if_coa, &sel);
-+ if ((ret = xfrm_mip_policy_add(&sel, 0, XFRM_POLICY_OUT,
-+ XFRM_POLICY_BLOCK,
-+ MIP6_PRIO_HOME_BLOCK, NULL, 0)))
-+ return ret;
-+ return ret;
-+}
-+
- /* blocking all payload packets from MN */
- int xfrm_block_link(struct home_addr_info *hai)
- {
-@@ -2141,6 +2241,21 @@ int xfrm_block_link(struct home_addr_inf
- MIP6_PRIO_HOME_BLOCK, NULL, 0)))
- return ret;
- return ret;
-+}
-+
-+void xfrm_unblock_bule_link(struct bulentry *bule)
-+{
-+ struct xfrm_selector sel;
-+ set_selector(&in6addr_any, &in6addr_any, 0, 0, 0, bule->if_coa, &sel);
-+ xfrm_mip_policy_del(&sel, XFRM_POLICY_OUT);
-+ /* RK: instead of deleting the policy, update it to its previous state
-+ * (the one installed in xfrm_cn_init) */
-+ set_selector(&in6addr_any, &in6addr_any, IPPROTO_ICMPV6,
-+ ND_NEIGHBOR_ADVERT, 0, 0, &sel);
-+ if (xfrm_mip_policy_add(&sel, 1 /* update */, XFRM_POLICY_OUT, XFRM_POLICY_ALLOW,
-+ MIP6_PRIO_NO_RO_SIG_ANY, NULL, 0) < 0)
-+ XDBG("Could not update NA policy\n");
-+ bule->home_block &= ~HOME_LINK_BLOCK;
- }
-
- void xfrm_unblock_link(struct home_addr_info *hai)
-diff -r 82fcd4bea972 src/xfrm.h
---- a/src/xfrm.h Fri Jan 11 16:55:08 2008 +0100
-+++ b/src/xfrm.h Fri Jan 11 17:02:25 2008 +0100
-@@ -51,7 +51,8 @@ int xfrm_add_bce(const struct in6_addr *
- int xfrm_add_bce(const struct in6_addr *our_addr,
- const struct in6_addr *peer_addr,
- const struct in6_addr *coa,
-- int replace);
-+ int replace,
-+ int create);
-
- void xfrm_del_bce(const struct in6_addr *our_addr,
- const struct in6_addr *peer_addr);
-@@ -82,7 +83,9 @@ int cn_wildrecv_bu_pol_add(void);
- int cn_wildrecv_bu_pol_add(void);
- void cn_wildrecv_bu_pol_del(void);
-
-+int xfrm_block_bule_link(struct bulentry *bule);
- int xfrm_block_link(struct home_addr_info *hai);
-+void xfrm_unblock_bule_link(struct bulentry *bule);
- void xfrm_unblock_link(struct home_addr_info *hai);
-
- int xfrm_block_hoa(struct home_addr_info *hai);
diff --git a/openair3/NEMO_SHO/mipv6-daemon-umip-0.4-sho-20080331.patch b/openair3/NEMO_SHO/mipv6-daemon-umip-0.4-sho-20080331.patch
deleted file mode 100755
index 50da24d540ffec86ccb927c89868829aefc29466..0000000000000000000000000000000000000000
--- a/openair3/NEMO_SHO/mipv6-daemon-umip-0.4-sho-20080331.patch
+++ /dev/null
@@ -1,978 +0,0 @@
-diff -Nru mipv6-daemon-umip-0.4-nepl-mcoa/extras/mr_mcoa_sho_UMIP.conf mipv6-daemon-umip-0.4-nepl-mcoa-sho/extras/mr_mcoa_sho_UMIP.conf
---- mipv6-daemon-umip-0.4-nepl-mcoa/extras/mr_mcoa_sho_UMIP.conf 1970-01-01 01:00:00.000000000 +0100
-+++ mipv6-daemon-umip-0.4-nepl-mcoa-sho/extras/mr_mcoa_sho_UMIP.conf 2008-03-31 17:06:27.000000000 +0200
-@@ -0,0 +1,67 @@
-+# This is an example of mip6d Mobile Node configuration file
-+
-+NodeConfig MN;
-+
-+## If set to > 0, will not detach from tty
-+DebugLevel 10;
-+
-+## Support route optimization with other MNs
-+DoRouteOptimizationCN disabled;
-+
-+## Use route optimization with CNs
-+DoRouteOptimizationMN disabled;
-+
-+UseCnBuAck disabled;
-+
-+Interface "eth0" {
-+ Bid 100;
-+ BidPriority 1;
-+ Reliable false;
-+ DefaultDelay 5000;
-+}
-+
-+Interface "eth1" {
-+ Bid 200;
-+ BidPriority 1;
-+ Reliable true;
-+ DefaultDelay 0;
-+}
-+
-+MnRouterProbes 1;
-+
-+MnHomeLink "eth0" {
-+ IsMobRtr enabled;
-+ MnUseSHO enabled;
-+# MnUseSHO disabled;
-+ MnUseAdaptiveCombining enabled;
-+# MnUseAdaptiveCombining disabled;
-+ HomeAgentAddress 2001:4::1;
-+ HomeAddress 2001:4::4/64 (2001:4:0:2::/64);
-+ RegMultipleCoA enabled;
-+ IfMultipleCoA "eth0", "eth1";
-+
-+ # proto type code route opt.
-+# MnRoPolicy ICMP 129 0 enabled;
-+# MnRoPolicy ICMP any any disabled;
-+ # proto dst src route opt.
-+# MnRoPolicy TCP 80 any enabled;
-+# MnRoPolicy TCP any any disabled;
-+}
-+
-+##
-+## IPsec configuration
-+##
-+
-+UseMnHaIPsec disabled;
-+
-+## Key Management Mobility Capability
-+KeyMngMobCapability disabled;
-+
-+IPsecPolicySet {
-+ HomeAgentAddress 3ffe:2620:6:1::1;
-+ HomeAddress 3ffe:2620:6:1::1234/64;
-+
-+ IPsecPolicy HomeRegBinding UseESP;
-+ IPsecPolicy MobPfxDisc UseESP;
-+ IPsecPolicy TunnelMh UseESP;
-+}
-diff -Nru mipv6-daemon-umip-0.4-nepl-mcoa/include/netinet/ip6mh.h mipv6-daemon-umip-0.4-nepl-mcoa-sho/include/netinet/ip6mh.h
---- mipv6-daemon-umip-0.4-nepl-mcoa/include/netinet/ip6mh.h 2008-03-21 16:40:07.000000000 +0100
-+++ mipv6-daemon-umip-0.4-nepl-mcoa-sho/include/netinet/ip6mh.h 2008-03-20 17:02:41.000000000 +0100
-@@ -157,6 +157,25 @@
- uint8_t ip6mobid_reserved;
- } __attribute__((packed));
-
-+/* NEMO-SHO */
-+struct ip6_mh_opt_fid {
-+ uint8_t ip6fid_type;
-+ uint8_t ip6fid_len;
-+ uint8_t ip6fid_flags_high;
-+ uint8_t ip6fid_flags_low;
-+ uint8_t ip6fid_fid;
-+ uint8_t ip6fid_action;
-+ uint8_t ip6fid_status;
-+ uint8_t ip6fid_pro_cls;
-+} __attribute__((packed));
-+
-+struct ip6_mh_opt_fid_subopt{
-+ uint8_t ip6fid_subopt_type;
-+ uint8_t ip6fid_subopt_len;
-+ uint8_t ip6fid_subopt_bid;
-+} __attribute__((packed));
-+/* NEMO-SHO */
-+
- /* Binding Unique Identifier sub-option flags */
- #if BYTE_ORDER == BIG_ENDIAN
- #define IP6_OPT_BID_BULK 0x80 /* Bulk Registration */
-@@ -187,6 +206,7 @@
- #define IP6_MHOPT_BAUTH 0x05 /* Binding Auth Data */
- #define IP6_MHOPT_MOB_NET_PRFX 0x06 /* Mobile Network Prefix */
- #define IP6_MHOPT_BID 0x07 /* Binding Unique Identifier */
-+#define IP6_MHOPT_FID 0x08 /* Flow Identification */
-
- /*
- * Status values accompanied with Mobility Binding Acknowledgement
-diff -Nru mipv6-daemon-umip-0.4-nepl-mcoa/src/bul.c mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/bul.c
---- mipv6-daemon-umip-0.4-nepl-mcoa/src/bul.c 2008-03-21 16:40:07.000000000 +0100
-+++ mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/bul.c 2008-03-20 16:55:16.000000000 +0100
-@@ -71,6 +71,7 @@
- bule->rules = 0;
- bule->home_block = 0;
- bule->mcoa_dereg = 1;
-+ bule->fid = 0; /* NEMO-SHO */
- INIT_LIST_HEAD(&bule->tqe.list);
- bule->seq = random();
- }
-diff -Nru mipv6-daemon-umip-0.4-nepl-mcoa/src/bul.h mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/bul.h
---- mipv6-daemon-umip-0.4-nepl-mcoa/src/bul.h 2008-03-21 16:40:07.000000000 +0100
-+++ mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/bul.h 2008-03-20 16:54:49.000000000 +0100
-@@ -43,6 +43,7 @@
- uint16_t seq; /* sequence number of the latest BU */
- uint16_t flags; /* BU send flags */
- uint16_t bid; /* MCoA: Binding Identifier */
-+ uint8_t fid; /* NEMO-SHO: Associated FID */
- struct in6_addr last_coa; /* Last good coa */
- struct timespec lastsent;
- struct timespec lifetime; /* lifetime sent in this BU */
-diff -Nru mipv6-daemon-umip-0.4-nepl-mcoa/src/cn.c mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/cn.c
---- mipv6-daemon-umip-0.4-nepl-mcoa/src/cn.c 2008-03-21 16:40:07.000000000 +0100
-+++ mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/cn.c 2008-03-20 17:12:02.000000000 +0100
-@@ -301,7 +301,7 @@
- status = IP6_MH_BAS_ACCEPTED;
- }
- if (bu_flags & IP6_MH_BU_ACK)
-- mh_send_ba(&out, status, 0, seqno, &lft, 0, 0, key, iif);
-+ mh_send_ba(&out, status, 0, seqno, &lft, 0, 0, NULL, key, iif); /* NEMO-SHO */
- return;
- send_nack:
- if (bce) {
-diff -Nru mipv6-daemon-umip-0.4-nepl-mcoa/src/conf.c mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/conf.c
---- mipv6-daemon-umip-0.4-nepl-mcoa/src/conf.c 2008-03-21 16:40:07.000000000 +0100
-+++ mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/conf.c 2008-03-21 15:29:32.000000000 +0100
-@@ -404,4 +404,27 @@
- }
- return priority;
- }
-+#if 1
-+// NEMO-SHO
-+/*
-+ * get_bid_from_ifindex - return the bid from the interface index
-+ * @iif: the interface index
-+ */
-+uint16_t get_delay_from_bid(uint16_t bid)
-+{
-+ struct list_head *list;
-+
-+ list_for_each(list, &conf.net_ifaces) {
-+ struct net_iface *nif;
-+ nif = list_entry(list, struct net_iface, list);
-+ if (nif->mn_if_bid == bid) {
-+ if (is_if_mn(nif))
-+ return nif->mn_if_delay;
-+ return 0;
-+ }
-+ }
-+
-+ return 0;
-+}
-+#endif
-
-diff -Nru mipv6-daemon-umip-0.4-nepl-mcoa/src/conf.h mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/conf.h
---- mipv6-daemon-umip-0.4-nepl-mcoa/src/conf.h 2008-03-21 16:40:07.000000000 +0100
-+++ mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/conf.h 2008-03-21 15:27:52.000000000 +0100
-@@ -45,6 +45,8 @@
- char MnDiscardHaParamProb;
- char SendMobPfxSols;
- char OptimisticHandoff;
-+ char MnUseSHO;
-+ char UseAdaptiveCombining;
-
- /* HA options */
- char HaAcceptMobRtr;
-@@ -70,6 +72,7 @@
- uint16_t mn_if_bid;
- uint8_t mn_if_bidprio;
- int mn_if_reliable;
-+ uint16_t mn_if_delay; /* NEMO-SHO option */
- };
-
- extern struct mip6_config conf;
-@@ -127,6 +130,7 @@
- uint16_t get_bid_from_ifindex(int iif);
- uint8_t get_prio_from_bid(uint16_t bid);
- uint8_t get_highest_prio();
-+uint16_t get_delay_from_bid(uint16_t bid);
-
- int yyparse(void);
-
-diff -Nru mipv6-daemon-umip-0.4-nepl-mcoa/src/gram.y mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/gram.y
---- mipv6-daemon-umip-0.4-nepl-mcoa/src/gram.y 2008-03-21 16:40:07.000000000 +0100
-+++ mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/gram.y 2008-03-21 15:49:44.000000000 +0100
-@@ -54,7 +54,8 @@
- .mn_if_preference = POL_MN_IF_DEF_PREFERENCE,
- .mn_if_bid = POL_MN_IF_DEF_BID,
- .mn_if_bidprio = POL_MN_IF_DEF_BID_PRIORITY,
-- .mn_if_reliable = POL_MN_IF_DEF_RELIABLE
-+ .mn_if_reliable = POL_MN_IF_DEF_RELIABLE,
-+ .mn_if_delay = POL_MN_IF_DEF_DELAY
- };
-
- struct home_addr_info hai = {
-@@ -196,8 +197,11 @@
- %token BID
- %token BIDPRIORITY
- %token RELIABLE
-+%token DEFAULTDELAY
- %token REGMULTIPLECOA
- %token IFMULTIPLECOA
-+%token MNUSESHO
-+%token MNUSEAPC
-
- %token INV_TOKEN
-
-@@ -448,6 +452,20 @@
- }
- ni.mn_if_bidprio = $2;
- }
-+ | DEFAULTDELAY NUMBER ';'
-+ {
-+ if (ni.mn_if_preference) {
-+ uerror("You cannot set Default Delay if "
-+ "MnIfPreference is set.");
-+ return -1;
-+ }
-+ if ($2 < 0 || $2 > 65535) {
-+ uerror("DefDelay error "
-+ "(%d <= BidPriority <= %d)",0, 65535);
-+ return -1;
-+ }
-+ ni.mn_if_delay = $2;
-+ }
- | RELIABLE BOOL ';'
- {
- ni.mn_if_reliable = $2;
-@@ -543,6 +561,14 @@
- {
- hai.reg_mcoa = $2;
- }
-+ | MNUSESHO BOOL ';'
-+ {
-+ conf.MnUseSHO = $2;
-+ }
-+ | MNUSEAPC BOOL ';'
-+ {
-+ conf.UseAdaptiveCombining = $2;
-+ }
- | IFMULTIPLECOA iflist ';'
- ;
-
-diff -Nru mipv6-daemon-umip-0.4-nepl-mcoa/src/ha.c mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/ha.c
---- mipv6-daemon-umip-0.4-nepl-mcoa/src/ha.c 2008-03-21 16:40:07.000000000 +0100
-+++ mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/ha.c 2008-03-21 16:27:40.000000000 +0100
-@@ -60,6 +60,17 @@
- #include "ndisc.h"
- #include "prefix.h"
-
-+/* NEMO-SHO CONFIG */
-+#define NEMO_SHO_LTOH // Enable in case of low speed to high speed
-+#ifdef NEMO_SHO_LTOH
-+const static int NEMO_SHO_DEFAULT_DELAY1 = 0; // msec
-+const static int NEMO_SHO_DEFAULT_DELAY2 = 1000; // msec
-+#else
-+const static int NEMO_SHO_DEFAULT_DELAY1 = 0; // msec
-+const static int NEMO_SHO_DEFAULT_DELAY2 = 0; // msec
-+#endif
-+/* NEMO-SHO CONFIG*/
-+
- #define HA_DEBUG_LEVEL 1
-
- #if HA_DEBUG_LEVEL >= 1
-@@ -1007,6 +1018,12 @@
- struct home_tnl_ops_parm p;
- struct ip6_mh_opt_bid *bid_opt;
-
-+ /* NEMO-SHO */
-+ struct ip6_mh_opt_fid *fid_opt;
-+ struct ip6_mh_opt_fid_subopt *fid_opt_subopt;
-+ struct bcentry *bce_associated = NULL;
-+ /* NEMO-SHO */
-+
- pthread_dbg("thread started");
- restart:
- home_ifindex = 0;
-@@ -1035,6 +1052,10 @@
- out.bind_coa = NULL;
- out.local_coa = NULL;
- bid_opt = NULL;
-+ /* NEMO-SHO */
-+ fid_opt = NULL;
-+ fid_opt_subopt = NULL;
-+ /* NEMO-SHO */
-
- /* MCoA
- * We check if a BCE already exists for this HoA
-@@ -1322,6 +1343,85 @@
- }
- bcache_update_expire(bce);
- }
-+ /* NEMO-SHO */
-+ /* check if there is FID option */
-+ fid_opt = mh_opt(&arg->bu->ip6mhbu_hdr,
-+ &arg->mh_opts,
-+ IP6_MHOPT_FID);
-+ /* check if there is BID sub-option */
-+ if (fid_opt && (fid_opt->ip6fid_len > (sizeof(struct ip6_mh_opt_fid) - 2))){
-+ fid_opt_subopt = (struct ip6_mh_opt_fid_subopt*)(fid_opt+1);
-+ if (fid_opt_subopt->ip6fid_subopt_type == 1)
-+ MDBG("FID: BID Reference sub-option\n");
-+ else {
-+ MDBG("FID: Unknown sub-option. FID is not processed\n");
-+ fid_opt_subopt = NULL;
-+ }
-+ }
-+
-+ if (fid_opt){
-+ MDBG("FID option (FID=%d) action=%d, status=%d, pro=%d, cls=%d\n",
-+ fid_opt->ip6fid_fid, fid_opt->ip6fid_action, fid_opt->ip6fid_status,
-+ (fid_opt->ip6fid_pro_cls & 0xF0) >> 4,
-+ fid_opt->ip6fid_pro_cls & 0x0F);
-+ uint8_t action = fid_opt->ip6fid_action;
-+ switch ( fid_opt->ip6fid_pro_cls & 0xF0){
-+ case FBIND_ADD_FLOW:
-+ MDBG("FID: ADD FLOW\n");
-+ if ( (action == FBIND_ACTION_NCAST) ||
-+ (action == FBIND_ACTION_NCAST_COMBINE )||
-+ (action == FBIND_ACTION_NCAST_COMBINE_ADAP) ){
-+ int nemo_sho_flag = SHO_BICAST;
-+ if (conf.debug_level > 0)
-+ nemo_sho_flag |= SHO_DEBUG;
-+ if (action == FBIND_ACTION_NCAST_COMBINE)
-+ nemo_sho_flag |= SHO_COMBINING;
-+ else if (action == FBIND_ACTION_NCAST_COMBINE_ADAP)
-+ nemo_sho_flag |= (SHO_COMBINING|SHO_ADAPTIVE);
-+
-+ assert(fid_opt_subopt);
-+ MDBG("FID: ACTION NCAST (SHO_FLAG=%x)\n", nemo_sho_flag);
-+ // look up another bcache assigned to bid
-+ bce_associated = bcache_get(out.src, out.dst,
-+ fid_opt_subopt->ip6fid_subopt_bid);
-+ if (bce_associated){
-+ if (dtunnel_mod_type(bce->tunnel,
-+ out.src,
-+ out.bind_coa,
-+ &bce_associated->coa,
-+ 0, // dummy
-+ nemo_sho_flag,
-+ 1, /* HA to MN/MR */
-+ NEMO_SHO_DEFAULT_DELAY1,
-+ NEMO_SHO_DEFAULT_DELAY2
-+ )< 0 ){
-+ }
-+ bcache_release_entry(bce_associated);
-+ }
-+ else
-+ MDBG("FID: no other binding cache entry\n");
-+ }
-+ else
-+ MDBG("FID: Unsupported Action\n");
-+ break;
-+ case FBIND_REMOVE_FLOW:
-+ MDBG("FID: REMOVE FLOW\n");
-+ dtunnel_mod_type(bce->tunnel,
-+ out.src,
-+ out.bind_coa,
-+ 0,
-+ 0, // dummy
-+ 0, // stop bicasting/combining
-+ 1 /* HA to MN/MR */,
-+ 0,
-+ 0);
-+ break;
-+ default:
-+ break;
-+ }
-+ }
-+ /* NEMO-SHO */
-+
- /* bce is always valid here */
- bcache_release_entry(bce);
- if (!tsisset(lft))
-@@ -1356,7 +1456,7 @@
-
- if (!(arg->flags & HA_BU_F_SKIP_BA))
- mh_send_ba(&out, status, ba_flags, seqno, &lft,
-- bid, bid_priority, NULL, iif);
-+ bid, bid_priority, fid_opt, NULL, iif); /* NEMO-SHO */
- /* MCoA: Start MPA only if no entries yet for this HoA */
- if (!bce_exists && new && tsisset(lft))
- mpd_start_mpa(&bce->our_addr, &bce->peer_addr);
-diff -Nru mipv6-daemon-umip-0.4-nepl-mcoa/src/mh.c mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/mh.c
---- mipv6-daemon-umip-0.4-nepl-mcoa/src/mh.c 2008-03-21 16:40:07.000000000 +0100
-+++ mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/mh.c 2008-03-20 17:11:24.000000000 +0100
-@@ -479,6 +479,62 @@
- return 0;
- }
-
-+/* NEMO-SHO
-+ * mh_create_opt_fid - Create a Flow Identifier Option
-+ * TODO1: (TBA)
-+ */
-+int mh_create_opt_fid(struct iovec *iov,
-+ uint8_t fid, uint8_t action, uint8_t status,
-+ uint8_t priority,
-+ uint8_t pro,
-+ int fid_subopt,
-+ uint8_t bid)
-+{
-+ int optlen = sizeof(struct ip6_mh_opt_fid) +
-+ (fid_subopt?sizeof(struct ip6_mh_opt_fid_subopt):0);
-+ struct ip6_mh_opt_fid *opt_fid;
-+ struct ip6_mh_opt_fid_subopt *opt_fid_subopt;
-+ uint8_t *data;
-+
-+ iov->iov_base = malloc(optlen);
-+ iov->iov_len = optlen;
-+
-+ if (iov->iov_base == NULL)
-+ return -ENOMEM;
-+
-+ memset(iov->iov_base, 0, iov->iov_len);
-+ data = (uint8_t *)iov->iov_base;
-+
-+ opt_fid = (struct ip6_mh_opt_fid *)data;
-+
-+#define IP6_OPT_FID_R 0x80
-+#define IP6_OPT_FID_H 0x40
-+
-+ opt_fid->ip6fid_type = IP6_MHOPT_FID;
-+ opt_fid->ip6fid_len = fid_subopt?9:6; // NEMO-SHO TODO: hard-coded
-+ opt_fid->ip6fid_flags_high = 0;
-+ opt_fid->ip6fid_flags_low = IP6_OPT_FID_H|priority; // TODO: priority should be masked
-+ opt_fid->ip6fid_fid = fid;
-+ opt_fid->ip6fid_action = action;
-+ opt_fid->ip6fid_status = status;
-+ opt_fid->ip6fid_pro_cls = (pro << 4) | 0x00;
-+ data += sizeof(struct ip6_mh_opt_fid);
-+
-+ if (fid_subopt){
-+ opt_fid_subopt = (struct ip6_mh_opt_fid_subopt *)data;
-+ opt_fid_subopt->ip6fid_subopt_type = 1;
-+ opt_fid_subopt->ip6fid_subopt_len = 3;
-+ opt_fid_subopt->ip6fid_subopt_bid = bid;
-+ data += sizeof(struct ip6_mh_opt_fid_subopt);
-+ }
-+
-+ MDBG("FID sub-option created with FID = %d and action %d\n",
-+ fid, action);
-+
-+ return 0;
-+}
-+/* NEMO-SHO */
-+
- static size_t mh_length(struct iovec *vec, int count)
- {
- size_t len = 0;
-@@ -526,6 +582,11 @@
- case IP6_MHOPT_BID:
- pad = optpad(2, 0, len); /* 2n */
- break;
-+ /* NEMO-SHO */
-+ case IP6_MHOPT_FID:
-+ pad = optpad(2, 0, len); /* 2n */
-+ break;
-+ /* NEMO-SHO */
- }
- if (pad > 0) {
- create_opt_pad(&out[n++], pad);
-@@ -1027,6 +1088,7 @@
- const struct timespec *lifetime,
- const uint16_t bid,
- const uint8_t priority,
-+ const struct ip6_mh_opt_fid *opt_fid, /* NEMO-SHO */
- const uint8_t *key, int iif)
- {
- int iovlen = 1;
-@@ -1058,6 +1120,18 @@
- /* MCoA: Create Binding Unique Identifier Option if needed */
- if (bid)
- mh_create_opt_bid(&mh_vec[iovlen++], bid, priority, 0);
-+
-+ /* NEMO-SHO: FID option if needed & BA is accepted */
-+ if (opt_fid && (status == IP6_MH_BAS_ACCEPTED))
-+ mh_create_opt_fid(&mh_vec[iovlen++],
-+ opt_fid->ip6fid_fid, //fid
-+ opt_fid->ip6fid_action, //action (n-casting)
-+ 0, //status
-+ 0, //priority
-+ opt_fid->ip6fid_pro_cls, //process
-+ 0,0); //subopt is not present
-+ /* NEMO-SHO */
-+
- mh_send(addrs, mh_vec, iovlen, key, iif);
- free_iov_data(mh_vec, iovlen);
- }
-diff -Nru mipv6-daemon-umip-0.4-nepl-mcoa/src/mh.h mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/mh.h
---- mipv6-daemon-umip-0.4-nepl-mcoa/src/mh.h 2008-03-21 16:40:07.000000000 +0100
-+++ mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/mh.h 2008-03-21 16:27:24.000000000 +0100
-@@ -10,7 +10,7 @@
-
- /* If new types or options appear, these should be updated. */
- #define IP6_MH_TYPE_MAX IP6_MH_TYPE_BERROR
--#define IP6_MHOPT_MAX IP6_MHOPT_BID
-+#define IP6_MHOPT_MAX IP6_MHOPT_FID /* NEMO-SHO */
-
- struct in6_addr_bundle {
- struct in6_addr *src;
-@@ -45,6 +45,7 @@
- const struct timespec *lifetime,
- const uint16_t bid,
- const uint8_t priority,
-+ const struct ip6_mh_opt_fid *opt_fid, /* NEMO-SHO */
- const uint8_t *key, int iif);
-
- static inline void mh_send_ba_err(const struct in6_addr_bundle *addrs,
-@@ -56,7 +57,7 @@
- {
- struct timespec zero = { 0, 0 };
- mh_send_ba(addrs, status, flags, seqno, &zero,
-- bid, priority, key, iif);
-+ bid, priority, NULL, key, iif); /* NEMO-SHO */
- }
-
- void mh_send_be(struct in6_addr *dst,
-@@ -87,6 +88,14 @@
-
- int mh_create_opt_bid(struct iovec *iov, uint16_t bid, uint8_t priority,
- uint8_t bid_flags);
-+/* NEMO-SHO */
-+int mh_create_opt_fid(struct iovec *iov,
-+ uint8_t fid, uint8_t action, uint8_t status,
-+ uint8_t priority,
-+ uint8_t pro,
-+ int fid_subopt,
-+ uint8_t bid);
-+/* NEMO-SHO */
-
- static inline void *mh_opt(const struct ip6_mh *mh,
- const struct mh_options *mh_opts, uint8_t type)
-@@ -138,4 +147,13 @@
- void mh_handler_reg(uint8_t type, struct mh_handler *handler);
- void mh_handler_dereg(uint8_t type, struct mh_handler *handler);
-
-+/* NEMO-SHO FlowBinding */
-+#define FBIND_ADD_FLOW 0x00
-+#define FBIND_REMOVE_FLOW 0xF0
-+#define FBIND_ACTION_NCAST 0x03
-+#define FBIND_ACTION_NCAST_COMBINE 0x04
-+#define FBIND_ACTION_NCAST_COMBINE_ADAP 0x05
-+#define FBIND_FID_SHO 0x08
-+/* NEMO-SHO */
-+
- #endif
-diff -Nru mipv6-daemon-umip-0.4-nepl-mcoa/src/mn.c mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/mn.c
---- mipv6-daemon-umip-0.4-nepl-mcoa/src/mn.c 2008-03-21 16:40:07.000000000 +0100
-+++ mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/mn.c 2008-03-31 16:15:06.000000000 +0200
-@@ -67,6 +67,14 @@
- #include "dhaad_mn.h"
- #include "ipsec.h"
-
-+/* NEMO-SHO CONFIG */
-+uint16_t mcoa_get_previous_bid(struct home_addr_info *hai);
-+enum {
-+ TYPE_HO_DOWNWARD,
-+ TYPE_HO_UPWARD
-+};
-+/* NEMO-SHO CONFIG*/
-+
- #define MN_DEBUG_LEVEL 1
-
- #if MN_DEBUG_LEVEL >= 1
-@@ -396,6 +404,49 @@
- free_iov_data(iov, iov_ind);
- return -ENOMEM;
- }
-+ /* NEMO-SHO */
-+ if (hai->reg_mcoa && bule->bid && bule->fid){
-+ uint16_t prev_bid =
-+ mcoa_get_previous_bid(hai);
-+ uint8_t action;
-+ if (conf.MnUseSHO){
-+ if (conf.UseAdaptiveCombining)
-+ action = FBIND_ACTION_NCAST_COMBINE_ADAP;
-+ else
-+ action = FBIND_ACTION_NCAST_COMBINE;
-+ }
-+ else
-+ action = FBIND_ACTION_NCAST;
-+ // Start N-casting
-+ if ( bu->ip6mhbu_lifetime &&
-+ mh_create_opt_fid(&iov[iov_ind++],
-+ bule->fid, //fid
-+ action,
-+ 0, //status
-+ 0, //priority
-+ FBIND_ADD_FLOW, //process (adding)
-+ 1, //subopt is present
-+ prev_bid //bid
-+ ) < 0 ){
-+ free_iov_data(iov, iov_ind);
-+ return -ENOMEM;
-+ }
-+ // Stop N-casting
-+ else if (!bule->mcoa_dereg &&
-+ mh_create_opt_fid(&iov[iov_ind++],
-+ bule->fid, //fid
-+ action,
-+ 0, //status
-+ 0, //priority
-+ 0xF,//process (removing)
-+ 0, //subopt is not present
-+ 0 //bid
-+ ) < 0){
-+ free_iov_data(iov, iov_ind);
-+ return -ENOMEM;
-+ }
-+ }
-+ /* NEMO-SHO */
- if (bule->flags & IP6_MH_BU_MR && bu->ip6mhbu_lifetime &&
- bule->home->mnp_count > 0 && conf.MobRtrUseExplicitMode &&
- mh_create_opt_mob_net_prefix(&iov[iov_ind++],
-@@ -452,6 +503,27 @@
-
- return ret;
- }
-+/* NEMO-SHO */
-+uint16_t mcoa_get_previous_bid(struct home_addr_info *hai)
-+{
-+ struct list_head *l;
-+ int iif = hai->current_coa->iif;
-+
-+ if(!hai->reg_mcoa){
-+ MDBG("================================= reg_mcoa is 0\n");
-+ return 0;
-+ }
-+
-+ list_for_each(l, &hai->mcoa) {
-+ struct mn_addr *coa_entry;
-+ coa_entry = list_entry(l, struct mn_addr, list);
-+ if (coa_entry->iif != iif)
-+ return get_bid_from_ifindex(coa_entry->iif);
-+ }
-+ MDBG("================================= cannot find entry\n");
-+ return 0;
-+}
-+/* NEMO-SHO */
-
- struct mn_addr *mcoa_get_current_coa(struct home_addr_info *hai, int iif)
- {
-@@ -1121,6 +1193,24 @@
- }
- if (!homereg_expired) {
- bule->do_send_bu = 1;
-+ /* NEMO-SHO */
-+ if (conf.MnUseSHO){
-+ struct bulentry *bul_prev = NULL;
-+ uint16_t prev_bid =
-+ mcoa_get_previous_bid(hai);
-+ if (prev_bid)
-+ bul_prev = bul_get(hai, NULL,
-+ &hai->ha_addr,
-+ prev_bid);
-+
-+ if (hai->reg_mcoa && bul_prev) {
-+ MDBG("=====previous_bid %d=====\n", prev_bid);
-+ bule->fid = FBIND_FID_SHO;
-+ }
-+ else
-+ bule->fid = 0;
-+ }
-+ /* NEMO-SHO */
- mn_send_bu_msg(bule);
- bul_update_timer(bule);
- if (conf.OptimisticHandoff)
-@@ -1145,6 +1235,44 @@
- bule->if_tunnel = tunnel_mod(bule->if_tunnel, &hai->current_coa->addr,
- &hai->ha_addr, hai->current_coa->iif,
- mn_ext_tunnel_ops, hai);
-+ /* NEMO-SHO */
-+ if (bule->fid){
-+ int HOtype;
-+ // only Packet Combining is enabled for this moement
-+ int nemo_sho_flag = SHO_COMBINING;
-+ if (conf.UseAdaptiveCombining)
-+ nemo_sho_flag |=SHO_ADAPTIVE;
-+ if (conf.debug_level > 0)
-+ nemo_sho_flag |=SHO_DEBUG;
-+
-+ uint16_t prev_bid =
-+ mcoa_get_previous_bid(hai);
-+ struct bulentry *bul_prev = bul_get(hai, NULL, &hai->ha_addr,
-+ prev_bid);
-+ // share the same fid with another bul
-+ bul_prev->fid = bule->fid;
-+
-+ if (get_delay_from_bid(prev_bid) >
-+ get_delay_from_bid(bule->bid) )
-+ HOtype = TYPE_HO_DOWNWARD;
-+ else
-+ HOtype = TYPE_HO_UPWARD;
-+
-+ dtunnel_mod_type(bule->if_tunnel,
-+ &bule->coa,
-+ &bule->peer_addr,
-+ &bul_prev->coa,
-+ bule->if_coa,
-+ nemo_sho_flag,
-+ 0,
-+ (HOtype==TYPE_HO_DOWNWARD)?
-+ get_delay_from_bid(bule->bid):0,
-+ (HOtype==TYPE_HO_DOWNWARD)?
-+ get_delay_from_bid(prev_bid):0
-+ ); /* from MR to HA */
-+ }
-+ /* NEMO-SHO */
-+
- hai->if_tunnel = bule->if_tunnel;
- bule->last_coa = bule->coa;
- bule->coa_changed = 0;
-@@ -1351,6 +1479,9 @@
- {
- struct ip6_mh_binding_ack *ba;
- struct ip6_mh_opt_bid *bui;
-+ // NEMO-SHO
-+ struct ip6_mh_opt_fid *fid_opt = NULL;
-+ // NEMO-SHO
- struct mh_options mh_opts;
- struct bulentry *bule;
- struct timespec now, ba_lifetime, br_adv;
-@@ -1370,6 +1501,7 @@
- /* MCoA: Lookup in BA options for the BUI sub-option and the BID */
- bui = mh_opt(&ba->ip6mhba_hdr, &mh_opts, IP6_MHOPT_BID);
- bid = bui ? ntohs(bui->ip6mobid_bid) : MCOA_NO_BID;
-+ fid_opt = mh_opt(&ba->ip6mhba_hdr, &mh_opts, IP6_MHOPT_FID);
-
- bule = bul_get(NULL, in->dst, in->src, bid);
- if (!bule || bule->type != BUL_ENTRY) {
-@@ -1383,6 +1515,26 @@
- NIP6ADDR(in->local_coa != NULL ?
- in->local_coa : &in6addr_any),
- bid);
-+ if (fid_opt){
-+ struct home_addr_info *hai = mn_get_home_addr(in->dst);
-+ if (hai){
-+ MDBG("FID option (FID=%d) is attached. releasing Bicasting/Combining info\n", fid_opt->ip6fid_fid);
-+ bule = bul_get(hai, NULL, in->src,
-+ get_bid_from_ifindex(iif));
-+ if (bule->fid == fid_opt->ip6fid_fid){
-+ dtunnel_mod_type(bule->if_tunnel,
-+ &bule->coa,
-+ &bule->peer_addr,
-+ 0,
-+ 0,
-+ 0,
-+ 0,
-+ 0,
-+ 0); /* from MR to HA */
-+ }
-+ }
-+ hai = NULL;
-+ }
- pthread_rwlock_unlock(&mn_lock);
- return;
- }
-@@ -1554,6 +1706,44 @@
- dbg("Deleting bul entry\n");
- bul_delete(bule);
- } else {
-+ /* NEMO-SHO */
-+ if (bule->fid){
-+ int nemo_sho_flag = SHO_BICAST|SHO_COMBINING;
-+ dbg("DTUNNEL from %x:%x:%x:%x:%x:%x:%x:%x "
-+ "with coa %x:%x:%x:%x:%x:%x:%x:%x\n",
-+ NIP6ADDR(in->src), NIP6ADDR(in->local_coa));
-+
-+ if (conf.UseAdaptiveCombining)
-+ nemo_sho_flag |=SHO_ADAPTIVE;
-+ if (conf.debug_level > 0)
-+ nemo_sho_flag |=SHO_DEBUG;
-+
-+ struct home_addr_info *hai = bule->home;
-+ uint16_t prev_bid =
-+ mcoa_get_previous_bid(hai);
-+ struct bulentry *bul_prev = bul_get(hai, NULL,
-+ &hai->ha_addr,
-+ prev_bid);
-+ int HOtype;
-+ if (get_delay_from_bid(prev_bid) >
-+ get_delay_from_bid(bule->bid) )
-+ HOtype = TYPE_HO_DOWNWARD;
-+ else
-+ HOtype = TYPE_HO_UPWARD;
-+ dtunnel_mod_type(bule->if_tunnel,
-+ &bule->coa,
-+ &bule->peer_addr,
-+ &bul_prev->coa,
-+ bule->if_coa,
-+ nemo_sho_flag,
-+ 0,
-+ (HOtype==TYPE_HO_DOWNWARD)?
-+ get_delay_from_bid(bule->bid):0,
-+ (HOtype==TYPE_HO_DOWNWARD)?
-+ get_delay_from_bid(prev_bid):0
-+ ); /* from MR to HA */
-+ }
-+ /* NEMO-SHO */
- set_bule_lifetime(bule, &ba_lifetime, &br_adv);
- if (bule->flags & IP6_MH_BU_HOME) {
- dbg("Callback to bu_refresh after %d seconds\n",
-diff -Nru mipv6-daemon-umip-0.4-nepl-mcoa/src/movement.c mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/movement.c
---- mipv6-daemon-umip-0.4-nepl-mcoa/src/movement.c 2008-03-21 16:40:07.000000000 +0100
-+++ mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/movement.c 2008-03-31 14:43:09.000000000 +0200
-@@ -48,7 +48,7 @@
- #include "prefix.h"
- #include "conf.h"
-
--#define MD_DEBUG_LEVEL 1
-+#define MD_DEBUG_LEVEL 0
-
- #if MD_DEBUG_LEVEL >= 1
- #define MDBG dbg
-@@ -1411,10 +1411,13 @@
- if (old)
- md_expire_router(iface, old, new);
-
-+ //NEMO-SHO avoid blocking outbound traffic here
-+#if 0
- if (list_empty(&iface->coas) &&
- !(iface->iface_flags & MD_BLOCK_TRAFFIC)) {
- md_block_rule_add(iface);
- }
-+#endif
- new->used = 1;
- md_add_default_router(iface, new);
- __md_new_link(iface, link_changed);
-diff -Nru mipv6-daemon-umip-0.4-nepl-mcoa/src/policy.h mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/policy.h
---- mipv6-daemon-umip-0.4-nepl-mcoa/src/policy.h 2008-03-21 16:40:07.000000000 +0100
-+++ mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/policy.h 2008-03-21 15:43:20.000000000 +0100
-@@ -13,6 +13,7 @@
- #define POL_MN_IF_DEF_BID 0
- #define POL_MN_IF_DEF_BID_PRIORITY 0
- #define POL_MN_IF_DEF_RELIABLE 1
-+#define POL_MN_IF_DEF_DELAY 0
-
- struct ip6_mh_binding_update;
- struct nd_router_advert;
-diff -Nru mipv6-daemon-umip-0.4-nepl-mcoa/src/scan.l mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/scan.l
---- mipv6-daemon-umip-0.4-nepl-mcoa/src/scan.l 2008-03-21 16:40:07.000000000 +0100
-+++ mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/scan.l 2008-03-21 15:34:55.000000000 +0100
-@@ -139,11 +139,14 @@
- HaAcceptMobRtr { return HAACCEPTMOBRTR; }
- HaAcceptMCoAReg { return HAACCEPTMCOAREG; }
- MCoAReg { return MCOAREG; }
-+MnUseSHO { return MNUSESHO; }
-+MnUseAdaptiveCombining { return MNUSEAPC; }
- NoMCoAReg { return NOMCOAREG; }
- IsMobRtr { return ISMOBRTR; }
- Bid { return BID; }
- BidPriority { return BIDPRIORITY; }
- Reliable { return RELIABLE; }
-+DefaultDelay { return DEFAULTDELAY; }
- RegMultipleCoA { return REGMULTIPLECOA; }
- IfMultipleCoA { return IFMULTIPLECOA; }
- HaServedPrefix { return HASERVEDPREFIX; }
-diff -Nru mipv6-daemon-umip-0.4-nepl-mcoa/src/tunnelctl.c mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/tunnelctl.c
---- mipv6-daemon-umip-0.4-nepl-mcoa/src/tunnelctl.c 2008-03-21 16:40:07.000000000 +0100
-+++ mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/tunnelctl.c 2008-03-20 16:51:35.000000000 +0100
-@@ -315,6 +315,73 @@
- return res;
- }
-
-+// ---------------- rueegg -------------------------
-+int dtunnel_mod_type(int ifindex,
-+ struct in6_addr *local,
-+ struct in6_addr *remote,
-+ struct in6_addr *addr2,
-+ int link,
-+ int do_bicasting,
-+ int tnl_type,
-+ unsigned short defaultDeltaT1,
-+ unsigned short defaultDeltaT2)
-+{
-+ struct mip6_tnl *tnl;
-+ struct ip6_tnl_parm parm;
-+ struct ifreq ifr;
-+
-+ int res = -1;
-+
-+ pthread_mutex_lock(&tnl_lock);
-+
-+ TDBG("modifying mode of tunnel %d end points with "
-+ "from %x:%x:%x:%x:%x:%x:%x:%x "
-+ "to %x:%x:%x:%x:%x:%x:%x:%x\n",
-+ ifindex, NIP6ADDR(local), NIP6ADDR(remote));
-+
-+ tnl = get_tnl(ifindex);
-+ assert(tnl != NULL);
-+
-+ if (tnl->users == 1){
-+ memset(&parm, 0, sizeof(struct ip6_tnl_parm));
-+ parm.proto = IPPROTO_IPV6;
-+ parm.flags = IP6_TNL_F_MIP6_DEV|IP6_TNL_F_IGN_ENCAP_LIMIT;
-+ parm.hop_limit = 64;
-+ parm.laddr = *local;
-+ parm.raddr = *remote;
-+ parm.link = link;
-+ parm.dparms.dtnl_flag = do_bicasting; //rueegg
-+ if (do_bicasting) {
-+ parm.dparms.dtnl_type = tnl_type; //rueegg
-+ parm.dparms.addr2 = *addr2; //rueegg
-+ }
-+ parm.dparms.defaultDeltaT[0]=defaultDeltaT1;
-+ parm.dparms.defaultDeltaT[1]=defaultDeltaT2;
-+
-+ strcpy(ifr.ifr_name, tnl->parm.name);
-+ ifr.ifr_ifru.ifru_data = (void *)&parm;
-+
-+ if(ioctl(tnl_fd, SIOCCHGTUNNEL, &ifr) < 0) {
-+ TDBG("SIOCCHGTUNNEL failed status %d %s\n",
-+ errno, strerror(errno));
-+ pthread_mutex_unlock(&tnl_lock);
-+ return -1;
-+ }
-+ memcpy(&tnl->parm, &parm, sizeof(struct ip6_tnl_parm));
-+ TDBG("modified tunnel iface %s (%d)"
-+ "from %x:%x:%x:%x:%x:%x:%x:%x "
-+ "to %x:%x:%x:%x:%x:%x:%x:%x\n",
-+ tnl->parm.name, tnl->ifindex, NIP6ADDR(&tnl->parm.laddr),
-+ NIP6ADDR(&tnl->parm.raddr));
-+ res = tnl->ifindex;
-+ }
-+
-+ pthread_mutex_unlock(&tnl_lock);
-+ return res;
-+}
-+
-+// ---------- rueegg end -------------------
-+
- static int __tunnel_mod(struct mip6_tnl *tnl,
- struct in6_addr *local,
- struct in6_addr *remote,
-diff -Nru mipv6-daemon-umip-0.4-nepl-mcoa/src/tunnelctl.h mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/tunnelctl.h
---- mipv6-daemon-umip-0.4-nepl-mcoa/src/tunnelctl.h 2007-09-13 11:42:42.000000000 +0200
-+++ mipv6-daemon-umip-0.4-nepl-mcoa-sho/src/tunnelctl.h 2008-03-20 16:51:13.000000000 +0100
-@@ -28,6 +28,21 @@
- void *data),
- void *data);
-
-+/* NEMO-SHO by hirokazu */
-+#define SHO_BICAST 0x1
-+#define SHO_COMBINING 0x2
-+#define SHO_ADAPTIVE 0x4
-+#define SHO_DEBUG 0x8
-+int dtunnel_mod_type(int ifindex,
-+ struct in6_addr *local,
-+ struct in6_addr *remote,
-+ struct in6_addr *addr2,
-+ int link,
-+ int do_bicasting,
-+ int tnl_type,
-+ unsigned short defaultDeltaT1,
-+ unsigned short defaultDeltaT2);
-+/* NEMO-SHO by hirokazu */
-
- int tunnelctl_init(void);
-
diff --git a/openair3/NEMO_SHO/mipv6-daemon-umip-0.4.tar.gz b/openair3/NEMO_SHO/mipv6-daemon-umip-0.4.tar.gz
deleted file mode 100755
index 940362a1b530c14ae9105ecac74edb387ab8c724..0000000000000000000000000000000000000000
Binary files a/openair3/NEMO_SHO/mipv6-daemon-umip-0.4.tar.gz and /dev/null differ