feat(bird): Add net.match
This commit is contained in:
parent
8d0139925e
commit
ba033f9099
1 changed files with 39 additions and 2 deletions
|
@ -3,7 +3,7 @@ from __future__ import annotations
|
||||||
import itertools
|
import itertools
|
||||||
import re
|
import re
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from ipaddress import IPv4Address
|
from ipaddress import IPv4Address, IPv4Network, IPv6Network, ip_network
|
||||||
from typing import Any, Generic, Iterator, Literal, TypeVar
|
from typing import Any, Generic, Iterator, Literal, TypeVar
|
||||||
|
|
||||||
from pydantic import (
|
from pydantic import (
|
||||||
|
@ -89,12 +89,37 @@ class IPv4orIPv6(BaseModel):
|
||||||
ipv6: list[int] = Field(ge=0, min_items=2, max_items=2)
|
ipv6: list[int] = Field(ge=0, min_items=2, max_items=2)
|
||||||
|
|
||||||
|
|
||||||
|
class IPFlag(str):
|
||||||
|
@classmethod
|
||||||
|
def __get_validators__(cls):
|
||||||
|
yield cls.validate
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def validate(cls, v):
|
||||||
|
pattern = r"(?P<ip>.*?)(?P<flag>[+-]|\{[0-9]+,[0-9]+\})?$"
|
||||||
|
parts = re.match(pattern, v)
|
||||||
|
|
||||||
|
return (ip_network(parts.group("ip")), parts.group("flag"))
|
||||||
|
|
||||||
|
|
||||||
|
class NetMatch(BaseModel):
|
||||||
|
matches: list[IPFlag] = Field(alias="net.match")
|
||||||
|
|
||||||
|
|
||||||
class NetLength(BaseModel):
|
class NetLength(BaseModel):
|
||||||
length: IPv4orIPv6 = Field(alias="net.len")
|
length: IPv4orIPv6 = Field(alias="net.len")
|
||||||
|
|
||||||
|
|
||||||
Condition = (
|
Condition = (
|
||||||
Proto | Source | And | Or | Not | AsPathContains | AsPathLength | NetLength
|
Proto
|
||||||
|
| Source
|
||||||
|
| And
|
||||||
|
| Or
|
||||||
|
| Not
|
||||||
|
| AsPathContains
|
||||||
|
| AsPathLength
|
||||||
|
| NetLength
|
||||||
|
| NetMatch
|
||||||
)
|
)
|
||||||
|
|
||||||
And.update_forward_refs()
|
And.update_forward_refs()
|
||||||
|
@ -210,6 +235,18 @@ def str_of_condition(condition: Condition, ctx: bool) -> str:
|
||||||
else:
|
else:
|
||||||
return f"{min_v6} <= net.len && net.len <= {max_v6}"
|
return f"{min_v6} <= net.len && net.len <= {max_v6}"
|
||||||
|
|
||||||
|
case NetMatch(matches=matches):
|
||||||
|
if ctx.ipv4:
|
||||||
|
networks = [
|
||||||
|
m for m in matches if isinstance(m[0], IPv4Network)
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
networks = [
|
||||||
|
m for m in matches if isinstance(m[0], IPv6Network)
|
||||||
|
]
|
||||||
|
|
||||||
|
return f"net ~ [ {', '.join([f'{network}{str(flag)}' for (network, flag) in networks])} ]"
|
||||||
|
|
||||||
|
|
||||||
def lines_of_action(action: Action, ctx: Context) -> Iterable[str]:
|
def lines_of_action(action: Action, ctx: Context) -> Iterable[str]:
|
||||||
match action:
|
match action:
|
||||||
|
|
Loading…
Reference in a new issue